Skip to content

asm

点开头的都是指导汇编器和链接器的伪命令

1. x86

1.1. 语法

分为 AT&T 和 intel 语法

1.2. 寄存器

  • %rip 程序计数器 PC,指向下一条指令
  • 一般有 16 个通用寄存器,%al %ax %eax %rax 分别是 8, 16, 32, 64 位,%r8b %r8w %r8d %r8 同理
    • %rax 返回值
    • %rbx 调用函数前后需保证不变
    • %rcx 第 4 个参数
    • %rdx 第 3 个参数
    • %rsi 第 2 个参数
    • %rdi 第 1 个参数
    • %rbp 调用函数前后需保证不变,帧指针
    • %rsp 栈指针
    • %r8 第 5 个参数
    • %r9 第 6 个参数
    • %r10 随意修改
    • %r11 随意修改
    • %r12 调用函数前后需保证不变
    • %r13 调用函数前后需保证不变
    • %r14 调用函数前后需保证不变
    • %r15 调用函数前后需保证不变
  • 段寄存器?
  • 标志寄存器

1.3. 操作数

AT&T 语法

  • $0x123 立即数
  • 0x123 绝对寻址
  • (%rax, %rcx) a + c
  • 9(%rax, %rcx) a + c + 9
  • (%rax, %rcx, 4) a + c * 4
  • 9(%rax, %rcx, 4) a + c * 4 + 9

intel 语法

  • 0x123 立即数
  • [eax - 1] a - 1

1.4. 指令

AT&T 语法

  • 指令后缀 b w l q 分别是 8, 16, 32, 64 位
  • 运算结果存最后一个操作数
  • movq %rax, %rbxb = a
    • movl 会把目的寄存器的高 4 字节置 0
  • pushq %raxrsp -= 8, *rsp = a
  • popq %raxa = *rsp, rsp += 8
  • sar 有符号右移,shr 无符合右移

intel 语法

  • byte, word, dword, qword 后面跟 ptr,分别是 8, 16, 32, 64 位的寻址
  • 运算结果存第一个操作数
  • mov eax, 0a = 0

2. arm

2.1. 寄存器

31 个通用寄存器 xn/wn

  • x0..x30 64bit x0..x30 32bit
  • x0 返回值
  • x0..x7 参数
  • x8 返回值
  • fp/x29 栈帧(栈底)
  • lr/x30 返回地址

特殊寄存器

  • sp wsp 栈指针
  • cpsr 状态寄存器
    • n 负数
    • z 零
    • c 无符号溢出
    • v 有符号溢出
  • pc 程序计数器,不可直接访问
  • zr wzr 零寄存器(zr 可能要写成 xzr)

向量 / 浮点寄存器

  • armv8 一共 32 个向量 / 浮点寄存器
  • h0..h31 按 16-bit 使用
  • s0..s31 32-bit
  • d0..d31 64-bit
  • v0..v31 128-bit,用于 NEON
  • z0..z31 不定长,用于 SVE

2.2. 操作数

  • #233 #0xf #-1:立即数
  • [x1, #1]:访问 x1 + 1

2.3. 指令

  • mov x0, x1:x0 = x1
  • add x0, x1, x2:x0 = x1 + x2
  • ret:返回(可能有一个操作数,一般是 x30)
  • b b.le:跳转、条件跳转

2.4. 函数调用

整数参数从 x0 排到 x7,然后放到栈上;浮点参数从 v0 开始

返回值 x0

3. 优化相关

cmov 适合分支预测不准的情况,jump 适合数据依赖大而分支预测准的情况

4. 汇编实践

汇编要通过 C 预处理和汇编器生成 .o 文件,另外还要写个 .h。