认识汇编 - 寄存器
常规使用的寄存器
RAX, RBX, RCX, RDX, RSI, RDI, RBP, RSP, R8, R9, R10, R11, R12, R12, R13, R14, R15
其中RSP始终指向stack顶部的位址,在C编译风格的程式RBP指向局部变量顶部的位置
还有一个特殊的寄存器RIP始终指向下一条要执行的指令,也就是我们学过的程序计数器
RIP在使用者端不可写(read only)
64 32 16 8 8RAX, EAX, AX, AH, ALAL是最右边8位,AH是接着8位,AH和AL合起来是AX
在nasm语法中,取用寄存器大小直接依照上述写法即可
后面的寄存器如下:
rsi, esi, si, silrdi, edi, di, dilrsp, esp, sp, splr8, r8d, r8w, r8b列举了一些通用寄存器的常见用途
- rax: 存放函数的返回值
- rcx: 循环的迭代变量
(while i--)的i - rdx: 当两个寄存器合并使用成16位时,左边8位的内容
- rsi: 来源内容
- rdi: 目的内容
- rbp: 局部变量顶部
- rsp: stack顶部 (规定)
函数呼叫规范
Section titled “函数呼叫规范”呼叫函数时需要将参数内容放入对应的寄存器
linux使用的顺序为:
rdi, rsi, rdx, rcx, r8, r9, rsp(栈)
windows使用的顺序为:
rcx, rdx, r8, r9, rsp(栈)
rdi rsi rdxf(arg1, arg2, arg3)假设要呼叫一个函数f,参数需要先放入对应的地方,函数进入后会当作已经将参数放好了直接使用
超过的长度则全部放入堆叠中
SIMD寄存器
Section titled “SIMD寄存器”用于并行处理的寄存器(可以处理浮点数和整数)
XMM0 ~ XMM15 128 bitsYMM0 ~ YMM15 256 bitsZMM0 ~ ZMM31 512 bits包含特定的状态标志,有些指令运行过程会使用并依照情况亮灯
比如常用的ZF,当ZF亮了表示值为0,像是加减法和cmp都会触发
举个例子:
while(n--) {}我们只要一直执行dec递减1,使用jz 当ZF触发则跳转到另一个地方
但不是所有指令出现0都会ZF,常用的xor就不会触发,这部份请查找网络资料和Intel x86_64指令集文档
还有CF(进位)、SF(符号)、OF(溢位)、DF(方向)等
CS、DS、SS、ES、FS、GS
现在只剩FS和GS在多线程使用到,平时不会出现
以下是补充说明:
内存地址可以用 [segment:offset] 来表示,segment 就是这几个寄存器
比如bootloader以及早期的16 bits环境中,常用 [ds:si] 和 [es:di] 来表示内存地址
实际地址是 es × 16 + di,比如 es = 0x1000, di = 0x20,表示 0x10020 这个地址
当今x86_64使用的 fs 和 gs 是一般加法 [fs:0x12]是 fs + 0x12