通用寄存器
在汇编世界里,我们主要通过汇编指令来操纵两种东西:
- 寄存器
- 内存地址
通用寄存器
寄存器的位数
由于 x86-64 架构惊人的后向兼容性,同一个寄存器,我们可以使用其中的 8bit、16bit、32bit、64bit,以 ax 寄存器为例,分别是 ah/al、ax、eax、rax,如下图所示:
通用寄存器的逻辑结构一定要记住:
这就导致一个问题,从大的寄存器上往小的寄存器上 mov 没有问题,而从小的寄存器往大的寄存器上 mov 就需要使用 movsxd 或者 movsx 指令了:
寄存器有两种概念,逻辑上的和物理上的,分别是架构相关寄存器(architectural register)和物理寄存器(physical register)。前者是指令集(ISA)提供给编译器可见的,相当于 API 接口规范,一共 16 个通用寄存器;后者是硬件上实际设计的,软件领域不直接接触。最新的 CPU 可能有上百个实际的物理寄存器。当然了,对软件开发人员来说,我们只需要关注逻辑上的通用寄存器。
这 16 个逻辑上的通用寄存器如下所示:
寄存器 16bit / 32bit / 64bit | 主要用途 | 编号 |
---|---|---|
ax / eax / rax | 累加器 | 0 |
cx / ecx / rcx | 计数 | 1 |
dx / edx / rdx | I/O 指针 | 2 |
bx / ebx / rbx | DS 段的数据指针 | 3 |
sp / esp / rsp | 堆栈指针寄存器在堆栈操作中使用,PUSH 和 POP 指令是从 SP 寄存器得到现行堆栈段的段内偏移量,所以称 SP 寄存器为堆栈指针:stack pointer,SP 始终指向栈顶。 | 4 |
bp / ebp / rbp | BP 与 SS 连用,为访问现行堆栈段提供方便。通常 BP 寄存器在间接寻址中使用,操作数在堆栈段中,由 SS 段寄存器和 BP 组合形成操作数的地址,即 BP 中存放现行堆栈段中一个数据区的“基址”的偏移量,所以称 BP 为基址指针:base pointer | 5 |
si / esi / rsi | 变址寄存器(IndexRegister),它们主要用于存放存储单元在段内的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。变址寄存器不可分割成 8 位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。它们可作一般的存储器指针使用。在字符串操作指令的执行过程中,对它们有特定的要求,而且还具有特殊的功能。 存储器指针,串指令中的源操作数指针:source indexRegister |
6 |
di / edi / rdi | 存储器指针,串指令中的目的操作数指针:destination indexRegister | 7 |
r8 | ||
r9 | ||
r10 | ||
r11 | ||
r12 | ||
r13 | ||
r14 | ||
r15 |
编号一定要记住,后面有用
汇编就是在“寄存器与寄存器”或者“寄存器与内存”之间来回移动数据。
寄存器和内存编号(内存地址)的区别
没有区别,唯一的区别就是前者位于 cpu,后者位于内存
每个寄存器指向 16/32/64 位的空间
每个内存编号指向 8 位的空间,这也就是为什么说操作内存的最小单位是字节
常用指令
MOV 指令
1 | MOV DST,SRC ; DST:目标操作数 SRC:源操作数 |
作用:拷贝源操作数到目标操作数
- 源操作数可以是立即数、通用寄存器、段寄存器、或者内存单元.
- 目标操作数可以是通用寄存器、段寄存器或者内存单元.
- 操作数的宽度必须一样.
- 源操作数和目标操作数不能同时为内存单元.
ADD 指令
1 | ADD DST,SRC ; DST:目标操作数 SRC:源操作数 |
作用:目标操作数与源操作数相加,将结果存回目标操作数
示例:
1 | mov eax,1 |
SUB 指令
1 | SUB DST,SRC |
作用:目标操作数减去源操作数,将结果存回目标操作数
示例:
1 | mov eax,3 |
AND 指令
1 | AND DST,SRC |
作用:目标操作数和源操作数按位逻辑与操作,将结果存回目标操作数
示例:
1 | mov eax,111 ; eax = 0x00000111 = 0000000000000000000000000000000111 |
OR 指令
1 | OR DST,SRC |
作用:DST 和 SRC 按位逻辑或操作,将结果存回 DST
示例:
1 | mov eax,100 |
XOR 指令
1 | XOR DST,SRC |
作用:DST 和 SRC 按位逻辑异或操作,将结果存回 DST。异或是不同则真
示例:
1 | mov eax,101 |
NOT 指令
1 | not DST |
作用:对 DST 按位取反,将结果存回 DST
示例:
1 | mov eax,ffffffff |
LEA
Load Effective Address:加载有效地址,将源操作数的地址加载到目的寄存器中
MOV 指令可以通过内存地址读取数据,如果只是需要内存地址,就可以使用 LEA 指令