汇编基础教程(一)——寄存器介绍

合并两篇介绍寄存器的文章,增加了一点内容。

-------------------------------------------------------------------------------------分割线------------------------------------------------------------------------------------

在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)


数据寄存器主要用来保存操作数和运算结果等信息,从而节省读取操作数所需占用总线和访问存储器的时间。EAX、EBX、ECX、和EDX都是从16位寄存器AX、BX、CX和DX拓展而来(Extended),而AX等又是从8位寄存器AL(Accumulator Low)、AH(Accumulator High)合并而来,如下图:
寄存器.jpg
对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)


变址寄存器(Index Register)主要用于存放存储单元在段内的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。
同样的,ESI和EDI也是从SI和DI寄存器拓展而来,作为通用寄存器的一员,它们也可存储算术逻辑运算的操作数和运算结果。
但是对于某些汇编指令(eg:REP STOS)来说,它们有特殊的作用,这个以后讲到汇编指令的时候再详细介绍。
  • ESI 是一个非易失通用寄存器,常被用作指针。特别的,在rep 一类的指令中,esi 通常指向“源”。因为esi 中数据是不会改变的,所以esi 通常会存储不会变的数据
  • EDI 是一个非易失通用寄存器,常被用作指针。它和esi 差不多,只不过一般是作为“目标”指针。

指针寄存器(EBP、ESP)


指针寄存器(Pointer Register)主要用于存放堆栈内存储单元的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。它们对应的16位寄存器为BP和SP,主要用于访问堆栈内的存储单元,并且规定:
  • BP为基指针(Base Pointer)寄存器,用它可直接存取堆栈中的数据;
  • SP为堆栈指针(Stack Pointer)寄存器,用它只可访问栈顶。

  • EBP 是一个非易失通用寄存器,根据编译器的设置,它有两个截然不同的用途:要么作为框架指针,要么作为一般寄存器。若没有优化编译或者代码是手工写的,ebp 会在函数开头就保存着堆栈的位置(关于堆栈下文会详细讨论)。因为堆栈在整个函数过程中是不停变换的,将ebp 指向堆栈的原始位置可以使得方便使用存储在堆栈中的变量。这会在讨论堆栈是详谈。

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

段寄存器(ES、CS、SS、DS、FS、GS)


段寄存器是根据内存分段的管理模式而设置的。内存单元的物理地址由段寄存器的值和一个偏移量组合而成的,这样可用两个较少位数的值组合成一个可访问较大物理空间的内存地址。在不同工作方式下,段寄存器的作用是不同的:

实方式


该方式下段寄存器的大小为16-bit,CPU内部的段寄存器:
  • CS——代码段寄存器(Code Segment Register),其值为代码段的段值;
  • DS——数据段寄存器(Data Segment Register),其值为数据段的段值;
  • ES——附加段寄存器(Extra Segment Register),其值为附加数据段的段值;
  • SS——堆栈段寄存器(Stack Segment Register),其值为堆栈段的段值;
  • FS——附加段寄存器(Extra Segment Register),其值为附加数据段的段值;
  • GS——附加段寄存器(Extra Segment Register),其值为附加数据段的段值。

保护方式


该方式下,段寄存器的大小为32-bit,装入段寄存器的不再是段值,而是被成为“选择子”(Selector)的某个值。详细情况这里就不浪费篇幅介绍了,有兴趣的朋友可以去百度一下。

指令指针寄存器(EIP)


32位CPU把指令指针扩展到32位,并记作EIP,EIP的低16位与先前CPU中的IP作用相同。

指令指针EIP、IP(Instruction Pointer)是存放下次将要执行的指令在代码段的偏移量。这个就不作解释了。

原文地址:https://www.cnblogs.com/xiaowangba/p/6314762.html