arm64: arm64 プログラミング
文法
構文
AT&T
sub $0x8, %rsp
-
%
がついていればAT&T。 - 右オペランドに代入される。
-
gdb
やobjdump -d
はこの出力 - GCCのインラインアセンブラでも使える
Intel
sub rsp, 8
- 左オペランドに代入される。
- libcapstoneではこちらが使われていそう。
-
objdump -M intel -d
するとこっちが出せる。 -
gdb
でもset disassembly-flavor intel
すると使える。
メモリアクセス
AT&T
mov 0x10(%rbx), %r15
括弧 (
)
がつくとメモリアクセスになる。括弧の前の数字がオフセットになっており、この場合は RBX + 16
の位置がアクセスされている。
Intel
mov DWORD PTR [ebx], 2
という感じで書くらしい。size directiveを指定しない場合は推論される。
レジスタ
Registers in x86 Assembly を見た方が良い。
- rax : 汎用レジスタ
- rbx : 汎用レジスタ
- rcx : 汎用レジスタ
- rdx : 汎用レジスタ
- rsi : 汎用レジスタ
- rdi : 汎用レジスタ
- rbp : 汎用レジスタ
- rsp : 汎用レジスタ兼スタックポインタ
- r8 : 汎用レジスタ
- r9 : 汎用レジスタ
- r9 : 汎用レジスタ
- r10 : 汎用レジスタ
- r11 : 汎用レジスタ
- r12 : 汎用レジスタ
- r13 : 汎用レジスタ
- r14 : 汎用レジスタ
- r15 : 汎用レジスタ
- rip : プログラムカウンタ
- eflags : フラグレジスタ
- cs : セグメントレジスタ
- ss : セグメントレジスタ
- ds : セグメントレジスタ
- es : セグメントレジスタ
- fs : セグメントレジスタ
- gs : セグメントレジスタ
プレフィックス
-
e
: 32bit (例: %eax) -
r
: 64bit (例: %rax)
スタック関連
- %rbp: ベースポインタ。元のスタックポインタが入っている
- %rsp: スタックポインタ。デクリメントしてスタックを拡張する。
関数呼び出し
x86_64 で用いられる呼び出し規約は2種類ある。
- System V AMD64 ABI: Linux, macOS, FreeBSD, Solaris
- Microsoft x64 calling convention: Windows
System V AMD64 ABI
- 引数:
- 整数, ポインタ: RDI, RSI, RDX, RCX, R8, R9
- 不動小数点: XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7
- 残りはスタック。右から左にスタックに積む。
- 返り値:
- 整数64ビットまで: RAX
- 整数128ビットまで: RAX & RDX
- 不動小数点: XMM0 & XMM1
- caller/callee-save
- RBX, RSP, RBP, R12–R15: non-volatile (= callee save)
- RAX, RCX, RDX, RSI, RDI, R8-R11, XMM0-XMM15, YMM0-YMM15, ZMM0-ZMM31: volatile (= caller save)
- システムコールでは RCX の代わりに R10 を使用
命令
-
x86 and amd64 instruction reference
- 一番見やすいかも
-
General-Purpose Instructions (x86 Assembly Language Reference Manual)
- Intel/AMD Mnemonic を見る。
cmp命令
ステータスフラグ ZF
, CF
を更新する。
命令サフィックス
-
b
: 1バイト (8bit) -
w
: 2バイト (16bit) -
l
: 4バイト (32bit) -
q
: 8バイト (64bit)
メモリをオペランドに取るときは必ずサフィックスが必要。
開発環境
実行方法
Intel構文を使いたい場合は .intel_syntax noprefix
を書く。
a.s
.globl main
main:
mov $0, %rax
ret
$ gcc a.s
$ ./a.out
gdb
レジスタの値を見る
p/x $rdi
などすると %rdi がhexで見れる。 *(void **)($rsp + 0x10)
とすると 0x10(%rsp)
が見れる。
アセンブリレイアウト
-
layout src
: Cのソース -
layout split
: Cのソース + アセンブリ -
layout asm
: アセンブリ -
layout regs
: レジスタ + Cのソース or アセンブリ (直前のlayoutに依存)
C-x o
でウィンドウ切り替えで、↑↓でスクロール。C-x a
で閉じたり入ったりできる。
objdump
asmを眺める
objdump -d a.o
.text
が出てくる。
デバッグ情報を混ぜる
objdump -dS a.o