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 + c9(%rax, %rcx)a + c + 9(%rax, %rcx, 4)a + c * 49(%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, %rbx:b = a- movl 会把目的寄存器的高 4 字节置 0
pushq %rax:rsp -= 8, *rsp = apopq %rax:a = *rsp, rsp += 8- sar 有符号右移,shr 无符合右移
intel 语法
byte, word, dword, qword后面跟 ptr,分别是 8, 16, 32, 64 位的寻址- 运算结果存第一个操作数
mov eax, 0:a = 0
2. arm
2.1. 寄存器
31 个通用寄存器 xn/wn
x0..x3064bitx0..x3032bit- 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..s3132-bitd0..d3164-bitv0..v31128-bit,用于 NEONz0..z31不定长,用于 SVE
2.2. 操作数
#233#0xf#-1:立即数[x1, #1]:访问 x1 + 1
2.3. 指令
mov x0, x1:x0 = x1add x0, x1, x2:x0 = x1 + x2ret:返回(可能有一个操作数,一般是 x30)bb.le:跳转、条件跳转
2.4. 函数调用
整数参数从 x0 排到 x7,然后放到栈上;浮点参数从 v0 开始
返回值 x0
3. 优化相关
cmov 适合分支预测不准的情况,jump 适合数据依赖大而分支预测准的情况
4. 汇编实践
汇编要通过 C 预处理和汇编器生成 .o 文件,另外还要写个 .h。