x86_64 汇编
寄存器
通用寄存器
常用的寄存器有 16 个,其中一些是通用的,另外的是有特定含义的。
在指令集的发展中很多寄存器经历了特定寄存器到通用寄存器的转变,现存留的特定功能的寄存器很少了。
-
%rbp, register base pointer, 基址地址,比如函数起始位置 -
%rsp, register stack pointer, 栈指针 -
%rsi,%rdi, 常被用来处理字符串 -
%rax,%rbx,%rcx,%rdx, 以及%r9到%r15共 12 个通用寄存器
对于每个 64 位寄存器,还有特定的名称可以用来表示其中的 32位 / 16位 / 低8位 / 紧靠低8位的8位。 命名方式有两种:
| 64位 | 32位 | 16位 | 8位 | offset+8的8位 |
|---|---|---|---|---|
| %rax | %eax | %ax | %al (low) | %ah (high) |
| %r8 | %r8d | %r8w (word) | %r8l (low) | %r8h (high) |
%rip是指令寄存器,即程序运行的位置
浮点数寄存器
浮点数是用 x87 FPU 单独处理的,它有 8 个 80 位寄存器
r0到r7, 用于处理浮点数
它也有自己一套独立的指令集
表示
| 写法 | 含义 |
|---|---|
| x | 全局变量 x |
| %rax | 寄存器 %rax 中的值 |
| $56 | 常量 56 |
| (%rsp) | 寄存器 %rsp 所指向地址中的值 |
| -16(%rbp) | *(%rbp - 16) |
| -16(%rbp, %rcx, 8) | *(%rbp + %rcx * 8 - 16) |
指令
| 指令 | 参数 | 功能 | 例子 |
|---|---|---|---|
| MOV | src, dst | 拷贝 src 中的值到 dst | MOV (%edx),%eax |
| ADD | op1, op2_and_dst | op1 + op2 并存到 op2 | ADD %rbx,%rax |
| SUB | op1, op2_and_dst | op1 - op2 并存到 op2 | SUB %rbx,%rax |
| IMUL | op2 | %rax * op2 并将高 64 位存到 %rdx,低 64 位存到 %rax | IMUL %rbx |
| IDIV | op2 | (%rdx \<\< 64 + %rax) / op2 并将商存到 %rax,余数存到 %rdx | |
| INC | src_and_dst | 自增 1 | |
| DEC | src_and_dst | 自减 1 | |
| JMP | label | 直接跳转到 label 的位置,相当于 goto | JMP loop |
| CMP | op1, op2 | 比较 op1 和 op2,结果会暂存,然后接条件 jump 语句 | CMP $5,%rbx; JNE loop |
| PUSH | src | 将 src 的值压栈,注意栈是从高到低生长,%rsp 指向栈顶 | PUSH %rax |
| POP | dst | 栈顶弹出值到 dst,如果不要结果,直接 ADD $8, %rsp 即可 |
|
| CALL | func | 根据函数调用规则调用指定函数名 | CALL printf |
| SHR | cnt, val | 将 val 中的值右移 cnt 中值的位数 | |
| SHL | cnt, val | 将 val 中的值左移 cnt 中值的位数 | |
| AND | src, dst | dst &= src | |
| OR | src, dst | dst | = src |
| XOR | src, dst | dst ^= src | |
| NOT | dst | dst \~= dst |
后缀
指令可以根据处理的位数添加后缀
➤ B:1 字节 ➤ W:2 字节 ➤ L:4 字节 ➤ Q:8 字节
如:MOVB 移动 1 个字节,MOVW 2字节,MOVL 4字节,MOVQ 8字节
条件 jump
- JE, Jump if Equal
- JNE, Jump if Not Equal
- JL, Jump if Less than
- JLE, Jump if Less or Equal
- JG, Jump if Greater than
- JGE, Jump if Greater or Equal
函数调用
x86_64 有着不同常规(常规是压栈传参)的函数调用方式
简化版规则如下:
- 整数参数存到寄存器
%rdi,%rsi,%rdx,%rcx,%r8,%r9 - 浮点数参数存到
%xmm0到%xmm7 - 多出来的参数压栈
- 对于变长参数函数,用
%eax存浮点参数个数 - 函数退出的时候要保证恢复
%rbx,%rbp,%rsp,%r12到%r15 - 返回值存在
%eax