Assembly

レジスターとメモリー

CPU内部の作業場所と、データを置くメモリーの関係を理解します。

x86-64 Linux・NASM記法を対象にしています。

Assembly入門の講座一覧

01

代表的なレジスター

レジスターはCPU内部の高速な記憶場所です。raxは計算結果やシステムコール番号、rdi~rdxは引数、rspはスタックの位置に使われます。

名前用途の例
rax計算結果、システムコール番号
rdi第1引数、終了コード
rsi第2引数、アドレス
rdx第3引数、データ長
rspスタックの現在位置
02

movで値を移動する

movは元の値を消さず、コピー先へ値を置きます。レジスター間や定数からの移動に使います。

レジスター間のコピーASSEMBLY
mov rax, 8
mov rbx, rax
add rbx, 4
; raxは8、rbxは12
03

メモリーを読み書きする

ラベルはデータのアドレスを表します。角かっこを付けると、そのアドレスにある値を読み書きします。

数値を更新するASSEMBLY
section .data
    number dq 42

section .text
    mov rax, [number]
    add rax, 8
    mov [number], rax

dbは1バイト、dqは8バイトを確保します。mov rsi, messageはアドレス、mov al, [message]は先頭の値です。

04

アドレス計算とエンディアン

角かっこの中には基底レジスター、インデックス、倍率、変位を組み合わせて書けます。x86-64は多バイト整数を下位バイトから並べるリトルエンディアンなので、GDBでメモリーを調べるときは表示順にも注意します。

memory.asmASSEMBLY
section .data
    scores dq 70, 85, 92
    number dq 42
section .text
    global _start
_start:
    mov rcx, 2
    mov rax, [scores + rcx * 8]
    mov rdi, rax
    mov rax, 60
    syscall
ビルドCOMMAND
nasm -f elf64 memory.asm -o memory.o
ld memory.o -o memory
実行結果OUTPUT
echo $?
92
GDBでバイト順を確認COMMAND / OUTPUT
gdb ./memory
(gdb) x/8xb &number
0x...: 0x2a 0x00 0x00 0x00 0x00 0x00 0x00 0x00

number dq 42の42は16進数で0x2aです。最も下位のバイト0x2aが低いアドレスに置かれるため、これがリトルエンディアンの並びです。

05

配列の要素を読む

8バイト単位の配列ASSEMBLY
section .data
    scores dq 70, 85, 92

section .text
    mov rax, [scores]
    mov rbx, [scores + 8]
    add rax, rbx
    ; rax = 155
実行結果OUTPUT
70 + 85 = 155

1要素が8バイトなので、2番目の要素には+ 8でアクセスします。データのサイズとアドレスの計算を揃えましょう。