概要
paiza.ioでaarch64アセンブラやってみる。
amd64アーキテクチャ
amd64アーキテクチャ
-
汎用レジスタ:
64-bit幅29個。X0-X28 (64bitアクセス)または W0-W28 (32bitアクセス) -
フレームポインタ(FP):
汎用レジスタX29 -
リンクレジスタ(LR):
汎用レジスタX30。関数呼出命令(BL, Branch with Link)の実行後、戻り番地が入る。 -
スタックポインタ(SP):
汎用レジスタX31。16バイトalignであることに注意。 -
FPUレジスタ:
128-bit幅 32個。V0-V31 (128bitアクセス)。FPU命令からは64-bit以下でしかアクセスできない。 D0-D31(64bit), F0-F31(32bit), H0-H31(16bit), B0-B31(8bit)。 NEONコプロセッサが実行するSIMD命令では、128bitに複数のデータ(64-bitデータ2個、32-bitデータ4個、16-bitデータ8個、8-bitデータ16個)を入れて並列に計算を実行する。 -
関数呼出しでは、整数の実引数は8個まではレジスタ(X0-X7 or W0-W7)に入れて、それ以上はスタックに積んで渡す。
関数呼出しでは、実数の実引数は8個まではレジスタ(V0-X7)に入れて、それ以上はスタックに積んで渡す。
関数呼出の返り値はX0 (W0) に入れて返す。構造体を返す場合は、構造体のアドレスをX8に入れて返す。浮動小数点数の場合は V0に入れて返す。
関数呼出しでは、X0-X18の値は保存されない(volatile)。X19-X29とSP(X31)は保存する必要がある(non-volatile)。
関数呼出しでは、V0-X7およびV16-V31の値は保存されない(volatile)。V8-V15は保存する必要がある(non-volatile)。
X18がプラットフォームによって占有的に使用されている場合(例 Thread Context)は、18を使ってはいけない。
プラットフォームがX18を利用しているか否かはプラットフォームのABIに記載されている。
プラットフォームに依存しないコードを書くにはX18を使用しないこと。
X16, X17 はそれぞれ IP0 (1st intro-procedure-call scrach register), IP1 と呼ばれていて、 リンカによって使用されることがある。
すなわち、サブルーチンコールやbranch命令の前後で値がダイナミックリンカによって値が変更される場合がある。
それ以外の場合はtemporal registerとして使っても構わない。(Arm64のbranch 命令は前後1MByteの範囲しか直接飛べない)
ローカルなラベルは、最初の文字をLにすること。(数字だけのラベルの使用は推奨しない)。 -
A64 メモリアドレッシング
Addressing
Mode Example 説明
Base Register ldr w1, [x0] w1 = *x0
ldr x1, [x0] x1 = *x0
Base Register
- Offset ldr w1, [x0,20] x1 = *(x0 + 20)
ldr x2, [x1, x0] x2 = *(x1 + x0)
ldr w2, [x1, x0, lsl 2] w2 = *(x1 + (x0 << 2))
ldr w2, [x0, w1, uxtw 2] w2 = *(x0 + (w1 << 2))
Pre-indexed ldr w1, [x0, 4]! x0 += 4; w1 = *x0
ldr x1, [x0, 8]! x0 += 8; x1 = *x0
ldr x2, [x1, x0]! x2 = *(x1 + x0); x1 += x0
ldr x2, [x1, x0, lsl 2]! x2 = *(x1 + (x0 << 2)); x1 += x0 << 2
Post-indexed ldr w2, [x1], 4 w2 = *x1; x1 += 4
ldr x2, [x1], 8 x2 = *x1; x1 += 8
ldr x2, [x1], x0 x2 = *x1; x1 += x0
ldr x2, [x1], x0, lsl 2 x2 = *x1; x1 += x0 << 2
PC relative ldr x2, label x2 = *(pc + label_offset)
- 命令は32 bit幅固定なので、64bitのアドレスをレジスタにロードするには工夫が必要となる。
よく使われる方法は次の2通り。
「PC相対(±1Mbyte, 19bit+2)で指定されるアドレスに64bitデータを置いておく。
レジスタにデータが置いてあるアドレスをloadする。
そのアドレスからデータをレジスタにloadする
ldr x0, =tmp // データが置いてあるアドレス(tmpラベル)がx0に入る
ldr x0, [x0] // x0が指すアドレスから、64bitデータをx0に読み込む
.data
tmp: .quad 0x123456789abcdef0 // 64bitデータ
複数回に分けてレジスタにアドレスをロードする。
// [例] x0レジスタに 0x123456789abcdef0 をロードする
mov x0, #0x1234, lsl #48
movk x0, #0x5678, lsl #32
movk x0, #0x9abc, lsl #16
movk x0, #0xdef0
[MOV命令のフォーマット]
MOVK Xd, #imm16[, LSL #shift]
MOV Xd, #imm16[, LSL #shift]
MOV Xd, Xs
MOV Xd, operand2
MOV: (MOVe) 指定された16bitにデータ値を設定し、他のビットを0にする。
MOVK: (MOVe Keep) 指定された16bitにデータ値を設定するが、他のビットの値は変更しない。
LSL: (Logical Shift Left) 左論理シフト。指定できる値は 16, 32, 48のどれか。
operand2 は3種類(a register and a shift, a register and an extension operation, a small number and a shift)。 - aligning data
.data // データ領域の宣言 (プログラムコードは別領域の .text 領域に置かれる)
.byte 0x3f // 8bitデータ
.align 4 // アドレスが4byte単位(下2bitが0)になるように揃える
.word 0x12345678 // 32 bit データ
.quad 0x123456789abcdef0 // 64 bit データ
.octa 0x123456789abcdef0fedcba9876543210 // 128 bit データ - A64 条件ジャンプ命令
b.cond
cond Meaning
eq Equal 等しい
ne Not equal 等しくない
cs Carry set (identical to HS) キャリーが1
hs Unsigned higher or same (identical to CS) 符号なしで大か等しい
cc Carry clear (identical to LO) キャリーが0
lo Unsigned lower (identical to CC) 符号無しで小
mi Minus or negative result 負
pl Positive or zero result 正または0
vs Overflow オーバーフロー
vc No overflow オーバーフロー無し
hi Unsigned higher 符号ありで大
ls Unsigned lower or same 符号ありで小または等しい
ge Signed greater than or equal 符号付きで以上
lt Signed less than 符号付きで未満
gt Signed greater than 符号付きで大きい
le Signed less than or equal 符号付きで以下
al Always (default) 無条件
amd64ニーモニック
| ニーモニック | 説明 |
|---|---|
| ADC | Add with carry |
| ADCS | Add with carry, setting the condition flags |
| ADD (extended register) | Add (extended register) |
| ADD (immediate) | Add (immediate) |
| ADD (shifted register)~ | Add (shifted register) |
| ADDS (extended register) | Add (extended register), setting the condition flags |
| ADDS (immediate) | Add (immediate), setting the condition flags |
| ADDS (shifted register) | Add (shifted register), setting the condition flags |
| ADR | Address of label at a PC-relative offset |
| ADRL | pseudo-instruction |
| ADRP | Address of 4KB page at a PC-relative offset |
| AND (immediate) | Bitwise AND (immediate) |
| AND (shifted register) | Bitwise AND (shifted register) |
| ANDS (immediate) | Bitwise AND (immediate), setting the condition flags |
| ANDS (shifted register) | Bitwise AND (shifted register), setting the condition flags |
| ASR (register) | Arithmetic shift right (register) |
| ASR (immediate) | Arithmetic shift right (immediate) |
| ASRV | Arithmetic shift right variable |
| AT | Address translate |
| B.cond | Branch conditionally to a label at a PC-relative offset, with a hint that this is not a subroutine call or return |
| B | Branch unconditionally to a label at a PC-relative offset, with a hint that this is not a subroutine call or return |
| BFI | Bitfield insert, leaving other bits unchanged |
| BFM | Bitfield move, leaving other bits unchanged |
| BFXIL | Bitfield extract and insert at low end, leaving other bits unchanged |
| BIC (shifted register) | Bitwise bit clear (shifted register) |
| BICS (shifted register) | Bitwise bit clear (shifted register), setting the condition flags |
| BL | Branch with link, calls a subroutine at a PC-relative offset, setting register X30 to PC + 4 |
| BLR | Branch with link to register, calls a subroutine at an address in a register, setting register X30 to PC + 4 |
| BR | Branch to register, branches unconditionally to an address in a register, with a hint that this is not a subroutine return |
| BRK | Self-hosted debug breakpoint |
| CBNZ | Compare and branch if nonzero to a label at a PC-relative offset, without affecting the condition flags, and with a hint that this is not a subroutine call or return |
| CBZ | Compare and branch if zero to a label at a PC-relative offset, without affecting the condition flags, and with a hint that this is not a subroutine call or return |
| CCMN (immediate) | Conditional compare negative (immediate), setting condition flags to result of comparison or an immediate value |
| CCMN (register) | Conditional compare negative (register), setting condition flags to result of comparison or an immediate value |
| CCMP (immediate) | Conditional compare (immediate), setting condition flags to result of comparison or an immediate value |
| CCMP (register) | Conditional compare (register), setting condition flags to result of comparison or an immediate value |
| CINC | Conditional increment |
| CINV | Conditional invert |
| CLREX | Clear exclusive monitor |
| CLS | Count leading sign bits |
| CLZ | Count leading zero bits |
| CMN (extended register) | Compare negative (extended register), setting the condition flags and discarding the result |
| CMN (immediate) | Compare negative (immediate), setting the condition flags and discarding the result |
| CMN (shifted register) | Compare negative (shifted register), setting the condition flags and discarding the result |
| CMP (extended register) | Compare (extended register), setting the condition flags and discarding the result |
| CMP (immediate) | Compare (immediate), setting the condition flags and discarding the result |
| CMP (shifted register) | Compare (shifted register), setting the condition flags and discarding the result |
| CNEG | Conditional negate |
| CRC32B, CRC32H, CRC32W, CRC32X | CRC-32 checksum from byte, halfword, word or doubleword |
| CRC32CB, CRC32CH, CRC32CW, CRC32CX | CRC-32C checksum from byte, halfword, word, or doubleword |
| CSEL | Conditional select, returning the first or second input |
| CSET | Conditional set |
| CSETM | Conditional set mask |
| CSINC | Conditional select increment, returning the first input or incremented second input |
| CSINV | Conditional select inversion, returning the first input or inverted second input |
| CSNEG | Conditional select negation, returning the first input or negated second input |
| DC | Data cache operation |
| DCPS1 | Debug switch to exception level 1 |
| DCPS2 | Debug switch to exception level 2 |
| DCPS3 | Debug switch to exception level 3 |
| DMB | Data memory barrier |
| DRPS | Debug restore process state |
| DSB | Data synchronization barrier |
| EON (shifted register) | Bitwise exclusive OR NOT (shifted register) |
| EOR (immediate) | Bitwise exclusive OR (immediate) |
| EOR (shifted register) | Bitwise exclusive OR (shifted register) |
| ERET | Returns from an exception |
| EXTR | Extract register from pair of registers |
| HINT | Hint instruction |
| HLT | External debug breakpoint |
| HVC | Hypervisor call to allow OS code to call the Hypervisor |
| IC | Instruction cache operation |
| ISB | Instruction synchronization barrier |
| LSL (register) | Logical shift left (register) |
| LSL (immediate) | Logical shift left (immediate) |
| LSLV | Logical shift left variable |
| LSR (register) | Logical shift right (register) |
| LSR (immediate) | Logical shift right (immediate) |
| LSRV | Logical shift right variable |
| MADD | Multiply-add |
| MNEG | Multiply-negate |
| MOV (to or from SP) | Move between register and stack pointer |
| MOV (inverted wide immediate) | Move inverted 16-bit immediate to register |
| MOV (wide immediate) | Move 16-bit immediate to register |
| MOV (bitmask immediate) | Move bitmask immediate to register |
| MOV (register) | Move register to register |
| MOVK | Move 16-bit immediate into register, keeping other bits unchanged |
| MOVL pseudo-instruction | Load a register |
| MOVN | Move inverse of shifted 16-bit immediate to register |
| MOVZ | Move shifted 16-bit immediate to register |
| MRS | Move from system register |
| MSR (immediate) | Move immediate to process state field |
| MSR (register) | Move to system register |
| MSUB | Multiply-subtract |
| MUL | Multiply |
| MVN | Bitwise NOT (shifted register) |
| NEG (shifted register) | Negate |
| NEGS | Negate, setting the condition flags |
| NGC | Negate with carry |
| NGCS | Negate with carry, setting the condition flags |
| NOP | No operation |
| ORN (shifted register) | Bitwise inclusive OR NOT (shifted register) |
| ORR (immediate) | Bitwise inclusive OR (immediate) |
| ORR (shifted register) | Bitwise inclusive OR (shifted register) |
| RBIT | Reverse bit order |
| RET | Return from subroutine, branches unconditionally to an address in a register, with a hint that this is a subroutine return |
| REV | Reverse bytes |
| REV16 | Reverse bytes in 16-bit halfwords |
| REV32 | Reverse bytes in 32-bit words |
| ROR (immediate) | Rotate right (immediate) |
| ROR (register) | Rotate right (register) |
| RORV | Rotate right variable |
| SBC | Subtract with carry |
| SBCS | Subtract with carry, setting the condition flags |
| SBFIZ | Signed bitfield insert in zero, with sign replication to left and zeros to right |
| SBFM | Signed bitfield move, with sign replication to left and zeros to right |
| SBFX | Signed bitfield extract |
| SDIV | Signed divide |
| SEV | Send event |
| SEVL | Send event locally |
| SMADDL | Signed multiply-add long |
| SMC | Supervisor call to allow OS or Hypervisor code to call the Secure Monitor |
| SMNEGL | Signed multiply-negate long |
| SMSUBL | Signed multiply-subtract long |
| SMULH | Signed multiply high |
| SMULL | Signed multiply long |
| SUB (extended register) | Subtract (extended register) |
| SUB (immediate) | Subtract (immediate) |
| SUB (shifted register) | Subtract (shifted register) |
| SUBS (extended register) | Subtract (extended register), setting the condition flags |
| SUBS (immediate) | Subtract (immediate), setting the condition flags |
| SUBS (shifted register) | Subtract (shifted register), setting the condition flags |
| SVC | Supervisor call to allow application code to call the OS |
| SXTB | Signed extend byte |
| SXTH | Signed extend halfword |
| SXTW | Signed extend word |
| SYS | System instruction |
| SYSL | System instruction with result |
| TBNZ | Test bit and branch if nonzero to a label at a PC-relative offset, without affecting the condition flags, and with a hint that this is not a subroutine call or return |
| TBZ | Test bit and branch if zero to a label at a PC-relative offset, without affecting the condition flags, and with a hint that this is not a subroutine call or return |
| TLBI | TLB invalidate operation |
| TST (immediate) | Test bits (immediate), setting the condition flags and discarding the result |
| TST (shifted register) | Test bits (shifted register), setting the condition flags and discarding the result |
| UBFIZ | Unsigned bitfield insert in zero, with zeros to left and right |
| UBFM | Unsigned bitfield move, with zeros to left and right |
| UBFX | Unsigned bitfield extract |
| UDIV | Unsigned divide |
| UMADDL | Unsigned multiply-add long |
| UMNEGL | Unsigned multiply-negate long |
| UMSUBL | Unsigned multiply-subtract long |
| UMULH | Unsigned multiply high |
| UMULL | Unsigned multiply long |
| UXTB | Unsigned extend byte |
| UXTH | Unsigned extend halfword |
| WFE | Wait for event |
| WFI | Wait for interrupt |
| YIELD | Yield hint |