合并两篇介绍寄存器的文章,增加了一点内容。
-------------------------------------------------------------------------------------分割线------------------------------------------------------------------------------------
在32位操作系统里面,一共有16个寄存器,分别是:4个数据寄存器(EAX、EBX、ECX和EDX)、2个变址寄存器(ESI和EDI)、2个指针寄存器(ESP和EBP)、6个段寄存器(ES、CS、SS、DS、FS和GS)、1个指令指针寄存器(EIP)和1个标志寄存器(EFlags)。
首先介绍一下易失性
一些寄存器在函数中常常是变化的,而另外一些却是不变的。这是编译器所决定的。因为寄存器是不会自动保存的(虽然有些汇编语言会自动保存,但是x86 是不会的),所以编码时要自己保存。这句话的意思是:当一个函数被调用,是不保证在函数返回时,易失寄存器上的值不变的;但是函数必须负责保存非易失寄存器中的值。
微软编译器的寄存器使用习惯如下:
1) 易失寄存器: ECX, EDX
2) 非易失寄存器 : EBX, ESI, EDI, EBP
3) 其他特殊寄存器 : EAX, ESP (discussed later)
数据寄存器(EAX、EBX、ECX、EDX)
对16位寄存器进行操作的时候,是不影响高16位的数据的,在16位寄存器中:
- 寄存器AX通常称为累加器(Accumulator),累加器可用于乘、除、输入/输出等操作,它们的使用频率很高;
- 寄存器BX称为基地址寄存器(Base Register)。它可作为存储器指针来使用;
- 寄存器CX称为计数寄存器(Count Register)。在循环和字符串操作时,要用它来控制循环次数;在位操作中,当移多位时,要用CL来指明移位的位数;
- 寄存器DX称为数据寄存器(Data Register)。在进行乘、除运算时,它可作为默认的操作数参与运算,也可用于存放I/O的端口地址。
它们(16位寄存器)不能作为基址和变址寄存器来存放存储单元的地址,但在32位CPU中,其32位寄存器EAX、EBX、ECX和EDX不仅可传送数据、暂存数据保存算术逻辑运算结果,而且也可作为指针寄存器,所以,这些32位寄存器更具有通用性。
- EAX 是一个32 为通用寄存器,一般的用途有两个:保存函数的返回值或者作为计算用的专用寄存器。在技术上来说,eax是一个易失寄存器,因为它的值是不能保存的,eax 的值通常会在函数返回前设置为函数的返回值。
- EBX 是一个非易失通用寄存器。它没有特定的用途,但是常被置为一个函数中常用的值(如0 ),以此来加快计算速度。
- ECX 是一个易失通用寄存器。常被用作函数的参数或者是循环的计数器。__fastcall 的函数会将第一和第二个参数放置在ecx 和edx 寄存器中。另外,当调用一个类中的成员函数时,不管调用习惯是什么,指向类的指针常常是放在ecx 中。另外,ecx 常被用作循环计算器。For 循环一般(尽管不是总是)会将循环计数放在ecx 中。Rep 指令也会将ecx 作为计数器,自动减少直到为0. 这类功能将在后面讨论。
- EDX 是一个易失通用寄存器,偶尔会被用作函数的参数。就像ecx ,edx 常用在__fastcall 调用的函数中。除了fastcall 调用中存放参数,编译器通常会将局部(短期)变量储存在edx 中。
变址寄存器(ESI、EDI)
同样的,ESI和EDI也是从SI和DI寄存器拓展而来,作为通用寄存器的一员,它们也可存储算术逻辑运算的操作数和运算结果。
但是对于某些汇编指令(eg:REP STOS)来说,它们有特殊的作用,这个以后讲到汇编指令的时候再详细介绍。
指针寄存器(EBP、ESP)
- BP为基指针(Base Pointer)寄存器,用它可直接存取堆栈中的数据;
- SP为堆栈指针(Stack Pointer)寄存器,用它只可访问栈顶。
EBP 是一个非易失通用寄存器,根据编译器的设置,它有两个截然不同的用途:要么作为框架指针,要么作为一般寄存器。若没有优化编译或者代码是手工写的,ebp 会在函数开头就保存着堆栈的位置(关于堆栈下文会详细讨论)。因为堆栈在整个函数过程中是不停变换的,将ebp 指向堆栈的原始位置可以使得方便使用存储在堆栈中的变量。这会在讨论堆栈是详谈。
- ESP 是一个保存着堆栈底端指针的特殊寄存器(堆栈是向低地址生长)。很少直接对ESP 进行数学计算(加减),而且函数的开始和结束时的ESP 值必须一致。Esp 下文介绍。
段寄存器(ES、CS、SS、DS、FS、GS)
实方式
- CS——代码段寄存器(Code Segment Register),其值为代码段的段值;
- DS——数据段寄存器(Data Segment Register),其值为数据段的段值;
- ES——附加段寄存器(Extra Segment Register),其值为附加数据段的段值;
- SS——堆栈段寄存器(Stack Segment Register),其值为堆栈段的段值;
- FS——附加段寄存器(Extra Segment Register),其值为附加数据段的段值;
- GS——附加段寄存器(Extra Segment Register),其值为附加数据段的段值。
保护方式
指令指针寄存器(EIP)
32位CPU把指令指针扩展到32位,并记作EIP,EIP的低16位与先前CPU中的IP作用相同。
指令指针EIP、IP(Instruction Pointer)是存放下次将要执行的指令在代码段的偏移量。这个就不作解释了。