汇编-32位寄存器的功能及其使用


总体上来讲32位寄存器可以分为一下几种:

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

Eax 是一个32 为通用寄存器,一般的用途有两个:保存函数的返回值或者作为计算用的专用寄存器。在技术上来说,eax 是一个易失寄存器,因为他的值是不能保存的,eax 的值会在函数返回前设置为函数的返回值。除了ESP 寄存器,EAX 的这个功能(即保存返回值)可能是最重要的值得被记住的。eax

下面是C 语言中函数返回的例子:

return 3;  // 返回3

对应的汇编语言:

mov eax, 3 ; 置EAX=3

ret        ; 返回

ebx

Ebx 是一个非易失通用寄存器。它没有特定的用途,但是常被置为一个函数中常用的值(如0

ecx

Ecx 是一个易失通用寄存器。常被用作函数的参数或者是循环的计数器。

__fastcall 的函数会将第一和第二个参数放置在ecx 和edx 寄存器中。另外,当调用一个类中的成员函数时,不管调用习惯是什么,指向类的指针常常是放在ecx

另外,ecx 常被用作循环计算器。For 循环一般(尽管不是总是)会将循环计数放在ecx 中。Rep 指令也会将ecx 作为计数器,自动减少直到为0.

edx

Edx 是一个易失通用寄存器,偶尔会被用作函数的参数。就像ecx ,edx 常用在__fastcall

除了fastcall 调用中存放参数,编译器通常会将局部(短期)变量储存在edx

esi

Esi 是一个非易失通用寄存器,常被用作指针。特别的,在rep 一类的指令中,esi 通常指向“源”。因为esi 中数据是不会改变的,所以esi

edi

Esi 是一个非易失通用寄存器,常被用作指针。它和esi

ebp

Ebp 是一个非易失通用寄存器,根据编译器的设置,它有两个截然不同的用途:要么作为框架指针,要么作为一般寄存器。

若没有优化编译或者代码是手工写的,ebp 会在函数开头就保存着堆栈的位置(关于堆栈下文会详细讨论)。因为堆栈在整个函数过程中是不停变换的,将ebp

如果编译被优化,当堆栈指针的计算通过指针的移动值计算时(这可能有点乱——IDA 就是自动侦测并校准一个移动的堆栈指针),ebp

esp

最后说说esp ,esp 是一个保存着堆栈底端指针的特殊寄存器(堆栈是向低地址生长)。很少直接对ESP 进行数学计算(加减),而且函数的开始和结束时的ESP 值必须一致。Esp