異なるサイズのMOV
CoddyのAssemblyジャーニー「基礎」セクションの一部。レッスン 20/45。
これまでに、al(8 ビット)とrax(64 ビット)を使いました。しかし、ほかのサイズもあります。レジスタによって保持できるデータ量は異なります。
x86-64レジスタファミリ:
| レジスタ | サイズ | ビット数 | 使用する場面 |
|---|---|---|---|
rax | 8バイト | 64ビット | 完全な数値、アドレス、syscall番号 |
eax | 4バイト | 32ビット | raxの下位半分 |
ax | 2バイト | 16ビット | eaxの下位半分 |
al | 1バイト | 8ビット | axの下位半分(ビット0~7) |
ah | 1バイト | 8ビット | axの上位半分(ビット8~15) |
同じパターンが他のレジスタにも適用されます:
| 64ビット | 32ビット | 16ビット | 8ビット(low) |
|---|---|---|---|
rbx | ebx | bx | bl |
rcx | ecx | cx | cl |
rdx | edx | dx | dl |
rsi | esi | si | sil |
rdi | edi | di | dil |
サイズが重要な理由:
data を移動するとき、source と destination のサイズは一致している必要があります。一致していない場合、CPU は次の動作をする可能性があります:
- data の一部だけをコピーする
- 不明なメモリから追加のバイトをコピーする
- エラーを引き起こす
サイズが一致する例:
mov rax, 1000 ; 64ビットから64ビット(問題なし)
mov eax, 1000 ; 32ビットから32ビット(問題なし)
mov ax, 1000 ; 16ビットから16ビット(問題なし)
mov al, 5 ; 8ビットから8ビット(問題なし)サイズが一致しない場合に起こること:
mov rax, 0x123456789ABC ; 64ビット値
mov al, 0xFF ; al に 0xFF が入り、rax の他のビットは変更されないより小さい値をより大きなレジスタに移動すると、上位ビットは変わらずに残ります。これにより、予期しない結果が生じることがあります。
安全なルール:
ここまでのコースでは、メモリ内のすべてのデータは 1 バイトです。そのため、rax ではなく al を使用します。
dataを移動するときは、レジスタのサイズをメモリサイズと一致させる必要があります:
- メモリの1バイト →
al、bl、clなどを使用 - メモリの8バイト →
rax、rbx、rcxなどを使用
さまざまなメモリサイズについては第3章で学びます。
チャレンジ
次のデータアドレスはすでに作成されています:
source:1バイトの値(5)を含むdestination:空き領域(1バイト)
次の処理を行うアセンブリの行を2行書いてください:
sourceから値をalに読み込むalの値をdestinationに格納する
自分で試してみよう
section .data
msg db 'destination = '
msg_len equ $ - msg
section .bss
digit resb 1
section .text
global _start
_start:
; 学生のコードが最初に実行されます(sourceからロードし、destinationにストアします)
%include "solution.asm"
; destinationから保存された値をロードする
mov al, [destination]
; それを保存する
mov r12, rax
; "destination = " を出力する
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, msg_len
syscall
; 値を出力する
mov rax, r12
add rax, 48
mov [digit], al
mov rax, 1
mov rdi, 1
mov rsi, digit
mov rdx, 1
syscall
; 終了
mov rax, 60
mov rdi, 0
syscallこのレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
基礎のすべてのレッスン
自分で練習してみよう: Assemblyプレイグラウンド