異なるサイズのMOV
CoddyのAssemblyジャーニー「基礎」セクションの一部 — レッスン 20/45。
すでに al (8ビット) と rax (64ビット) を使用しました。しかし、他のサイズもあります。レジスタによって保持できるデータの量が異なります。
x86-64 レジスタファミリ:
| レジスタ | サイズ | ビット | 使用場面 |
|---|---|---|---|
rax | 8 バイト | 64 ビット | 数値全体、アドレス、システムコール番号 |
eax | 4 バイト | 32 ビット | rax の下位半分 |
ax | 2 バイト | 16 ビット | eax の下位半分 |
al | 1 バイト | 8 ビット | ax の下位半分 (ビット 0-7) |
ah | 1 バイト | 8 ビット | ax の上位半分 (ビット 8-15) |
同じパターンが他のレジスタにも適用されます:
| 64ビット | 32ビット | 16ビット | 8ビット (下位) |
|---|---|---|---|
rbx | ebx | bx | bl |
rcx | ecx | cx | cl |
rdx | edx | dx | dl |
rsi | esi | si | sil |
rdi | edi | di | dil |
サイズが重要な理由:
データを移動するとき、転送元と転送先のサイズは一致している必要があります。一致しない場合、CPUは以下の動作を行う可能性があります:
- データの一部のみをコピーする
- 不明なメモリから余分なバイトをコピーする
- エラーを発生させる
一致するサイズの例:
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バイトです。そのため、al(raxではなく)を使用します。
データを移動するとき、レジスタのサイズはメモリのサイズと一致している必要があります:
- 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このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。