通用寄存器

用于传送和暂存数据,参与算数逻辑运算并保存运算结果。IA-32每个通用寄存器的大小都是32位,即4个字节,主要用来保存常量和地址等信息。

以下4个通用寄存器主要用于算术运算如ADD、SUB、XOR、OR等,常用于保存常量与变量的值。

EAX:(针对操作数和结果数据的)累加器,一般用在函数返回值中,所有Win32 API函数都会把返回值保存到EAX后再返回。EAX寄存器又分为高、低几个独立的寄存器,AX(0-15)为EAX(0-31)的低16位独立寄存器,而AX又分为高8位的AH(8-15)和低8位的AL(0-7)两个独立寄存器,下面的EBX、ECX和EDX同理。

EBX:(DS段中的数据指针)基址寄存器。

ECX:(字符串和循环操作的)计数器,如在循环命令LOOP中用来循环计数、每执行完一次循环ECX就自减一。

EDX:(I/O指针)数据寄存器。

以下4个通用寄存器主要用于保存内存地址的指针。

ESI:(字符串操作源指针)源变址寄存器。

EDI:(字符串操作目标指针)目的变址寄存器,ESI和EDI与特定指令(LODS、STOS、REP、MOVS等)一起使用,主要用于内存复制。

EBP:(SS段中栈内数据指针)扩展基址指针寄存器,表示栈区域的基地址,即指向栈最上面的一个栈帧的底部,函数被调用时保存ESP的值,函数返回时再把值返回ESP,保证栈不会崩溃(即栈帧技术)。

ESP:(SS段中栈指针)栈指针寄存器,指向栈区域的栈顶地址。

段寄存器

在IA-32的保护模式中,段是一种内存保护技术,将内存划分为多个区段,并为每个区段赋予起始地址、范围、访问权限等以保护内存。段内存记录在SDT中,而段寄存器持有这些SDT的索引。每个段寄存器的大小为16位,即2个字节,且每个段寄存器指向的段描述符与虚拟内存结合,形成一个线性地址,借助分页技术,线性地址最终被转换为实际的物理地址。

CS:Code Segment,代码段寄存器。

DS:Data Segment,数据段寄存器。

SS:Stack Segment,栈段寄存器。

ES:Extra (Data) Segment,附加(数据)段寄存器。

FS:Data Segment,数据段寄存器,在程序调试中经常用于计算SEH(结构化异常处理机制)、TEB(线程环境块)、PEB(进程环境块)。

GS:Data Segment,数据段寄存器。

其中ES、FS、GS寄存器用来存放程序使用的附加数据段的段基址。

程序状态与控制寄存器

EFLAGS:Flag Register,标志寄存器,大小为4个字节即32位,每一位都有意义,有些位由系统直接设定,有些位则根据程序命令的执行结果设置。

寄存器

先了解3个常用的与程序调试相关的标志,ZF(Zero Flag零标志)、OF(Overflow Flag溢出标志)、CF(Carry Flag进位标志)。

ZF:若运算结果为0,则为1(True),否则为0(False)。

OF:有符号整数溢出时,则为1。此外,MSB(最高有效位)改变时,也为1。

CF:无符号整数溢出时,则为1。

指令指针寄存器

EIP:Instruction Pointer,指令指针寄存器,保存着CPU要执行的指令地址,大小为32位即4个字节。

程序运行时,CPU会读取EIP中的一条指令地址,传送指令到指令缓冲区后,EIP寄存器的值将自动增加,增加的大小为读取指令的字节大小。CPU每次执行完一条指令,就会通过EIP寄存器读取并执行下一条指令。

注意的就是,EIP寄存器和通用寄存器不同,不能直接修改EIP的值,只能通过其他指令间接修改,如JMP、Jcc、CALL、RET。也可以通过中断或者异常来修改EIP的值。