Assembly

演算・分岐・ループ

命令が値とフラグを変え、その結果で実行位置が変わる流れを学びます。

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

Assembly入門の講座一覧

01

算術命令

addとsubは第1オペランドを変更します。imulは掛け算、incとdecは1増減です。

合計を計算するASSEMBLY
mov rax, 12
add rax, 8
sub rax, 5
imul rax, 3
; (12 + 8 - 5) * 3 = 45
実行結果OUTPUT
rax = 45
0で割れない divの前には、割る値が0でないことを確認します。割られる値はrdx:raxで受け取るため、符号なし整数ならxor rdx, rdx、符号付き整数ならcqoで上位側を準備します。
02

cmpとフラグ

cmpは結果を保存せず、比較結果をフラグへ反映します。条件ジャンプがそのフラグを読みます。

等しいか判定するASSEMBLY
mov rax, 10
cmp rax, 10
je equal
mov rdi, 1
jmp finish
equal:
    xor rdi, rdi
finish:

jeは等しい、jneは異なる、jgとjlは符号付きの大小比較です。

03

条件分岐を作る

ラベルへジャンプすることで、他の言語のifに相当する処理を表現できます。cmp left, rightの順番で大小判定の意味が変わります。

条件分岐を実行するASSEMBLY
section .text
    global _start
_start:
    mov rax, 10
    cmp rax, 10
    je equal
    mov rdi, 1
    jmp finish
equal:
    xor rdi, rdi
finish:
    mov rax, 60
    syscall
実行結果OUTPUT
echo $?
0
04

ループで配列を合計する

添字を増やすループASSEMBLY
section .data
    values dq 4, 7, 9, 2
    value_count equ 4

section .text
    xor rax, rax
    xor rcx, rcx
sum_loop:
    add rax, [values + rcx * 8]
    inc rcx
    cmp rcx, value_count
    jl sum_loop
    ; rax = 22

ループカウンターを更新し忘れると無限ループになります。終了条件と配列要素のサイズを毎回確認しましょう。