GDBで変化を追う
Assemblyでは、命令の前後でレジスターとメモリーがどう変わったかを確認します。
基本操作COMMAND
gdb ./hello
(gdb) break _start
(gdb) run
(gdb) info registers rax rdi rsi rdx
(gdb) stepi
(gdb) x/s $rsi
(gdb) quit練習問題
問題1:3つの数の合計
4、7、9の合計を終了コードで返してください。
解答例ASSEMBLY
mov rax, 4
add rax, 7
add rax, 9
mov rdi, rax
mov rax, 60
syscall実行結果OUTPUT
echo $?
20問題2:偶数かどうか
test rax, 1を使い、偶数なら0、奇数なら1を返してください。
解答例ASSEMBLY
mov rax, 14
test rax, 1
jnz odd
xor rdi, rdi
jmp finish
odd:
mov rdi, 1
finish:
mov rax, 60
syscall実行結果OUTPUT
echo $?
0問題3:配列の最大値
12、5、21、9をループで比較し、最大値を返してください。
解答例ASSEMBLY
scores dq 12, 5, 21, 9
mov rax, [scores]
mov rcx, 1
find_max:
cmp rcx, 4
jge finish
mov rbx, [scores + rcx * 8]
cmp rbx, rax
jle next
mov rax, rbx
next:
inc rcx
jmp find_max
finish:
mov rdi, rax
mov rax, 60
syscall実行結果OUTPUT
echo $?
21問題4:安全な割り算
割る値が0なら中止し、0でなければ23 / 5の商を返してください。
解答例ASSEMBLY
mov rax, 23
mov rbx, 5
cmp rbx, 0
je error
xor rdx, rdx
div rbx
mov rdi, rax
jmp finish
error:
mov rdi, 1
finish:
mov rax, 60
syscall実行結果OUTPUT
echo $?
4問題5:文字列の長さ
終端の0まで1バイトずつ調べ、Helloの長さを返してください。
解答例ASSEMBLY
message db "Hello", 0
mov rsi, message
xor rcx, rcx
count:
cmp byte [rsi + rcx], 0
je finish
inc rcx
jmp count
finish:
mov rdi, rcx
mov rax, 60
syscall実行結果OUTPUT
echo $?
5進め方 まず各レジスターの値を紙に書き、最小のソースを実行します。失敗したらエラー全文を読み、GDBで直前の命令を確認しましょう。
次に学ぶこと
数字の文字列変換、ファイル入出力、C言語との連携、ELF形式、呼び出し規約、SIMD命令へ進めます。常にCPU・OS・アセンブラーを確認する習慣を持ちましょう。
