汇编基础之二 -- 寄存器和内存堆栈
这里介绍8个通用寄存器和两个特殊的寄存器
其余寄存器https://blog.csdn.net/weixin_4427
8个通用寄存器
对于8个通用寄存器来说, 一个寄存器是一个4字节大小的物理单元,也就是数据宽度为DWORD,为了方便实现byte和word数据宽度的操作。又将这个寄存器再次进行划分。以EAX单元为例子。EAX是一个4字节的32位寄存器,为了方便对WORD数据宽度进行处理,将EAX低位的两个字节命名位AX寄存器,同样的。为了方便byte的操作。将AX的寄存器的高8位和低8位分别位AH和AL寄存器。如图:
根据这样的方式,8个寄存器再次被划分位多个子单元,得到了16和8位的寄存器。
16位 | 8位 | |
---|---|---|
EAX: | AX | AH、AL |
EBX | BX | BH、BL |
ECX | CX | CH、CL |
EDX | DX | DH、DL |
ESI:使用MOVS指令复制数据时,ESI储存源数据的地址 | SI | |
EDI:使用MOVS指令复制数据时,EDI储存复制的目的地址 | DI | |
ESP:储存程序栈顶的内存地址 | SP | |
EBP:储存程序栈底的内存地址 | BP |
如上表,只存在8个通用寄存器,然后被分成16位寄存器和8位寄存器,16位和8寄存器并没有专门分配硬件,而是与32位寄存器通用来实现。在32位CPU中,32位寄存器EAX、EBX、ECX和EDX可以用作传送数据、暂存数据,保存算术逻辑运算结果,同时也可以保存内存地址,即作为指针寄存器。
ESI, EDI有默认的用途,主要用于复制,两个寄存器中都存储内存中的地址,当使用MOVS指令进行复制时候,默认是将ESI内存地址处的数据复制到EDI保存的内存地址处,每次复制之后,ESI和EDI中保存的地址会对应的进行偏移,这样可以连续的复制内存中一串内存地址的数据。
ESP和EBP寄存器中记录的是当前程序的堆栈空间的地址。堆栈式计算机分配给程序的一段连续的内存块,例如分配给程序内存编号为1000 - 5000这段内存块,这个空间成为程序的堆栈,程序中的需要保存的数据暂存在这个空间中,并在ESP寄存器中记录内栈顶的地址(内存小编号),EBP中保存栈低的地址。
两个特殊的寄存器
EFL寄存器:该寄存器中的每一位用于表示一组的状态标志,用于提供程序的状态及进行相应的控制。该寄存器不能用于存储其他值。其标志位含义如下:
-
-
PF [Parity flag] 如果结果的最低有效字节(least-significant byte)包含偶数个1位则该位置1,否则清零
-
AF [Adjust flag] 如果算术操作在结果的第3位发生进位或借位则将该标志置1,否则清零。这个标志在BCD(binary-code decimal)算术运算中被使用。
-
ZF [Zero flag] 若结果为0则将其置1,反之清零。
-
SF [Sign flag] 该标志被设置为有符号整型的最高有效位。(0指示结果为正,反之则为负)
-
OF [Overflow flag] 由于有符号数最高位为符号位,则第二高位置发生了进位或者借位即可判断该数溢出。如果运算后第二高位发生了借位或者进位,该标志位置为1,反之清零。这个标志用于标志带符号整型运算指示溢出状态。
-
DF [Direction flag]:控制串指令(MOVS, CMPS, SCAS, LODS以及STOS)每次执行后会自动将内存地址进行递增或递减。设置DF标志为1,控制串指令每次操作的内存地址会自动递减(从高地址向低地址方向处理字符串),设置为0则使得串指令每次操作的地址为自动递增。STD以及CLD指令分别用于设置以及清除DF标志。
-
TF [Trap flag]:将该位设置为1以允许单步调试模式,清零则禁用该模式。
-
IF[Interrupt enable flag]:该标志用于控制处理器对可屏蔽中断请求(maskable interrupt requests)的响应。置1以响应可屏蔽中断,反之则禁止可屏蔽中断。
-
内存
计算机中最小的储存单位为字节,内存也不例外,每个字节作为一个储存单元。这样就将内存划分成了上亿个内存单元,为了方便管理这些单元,计算机选择了对每一个内存单元进行编号,想要使用一个内存单元时,只需要指定该内存单元编号(即内存地址)即可。为了能编号尽量多的地址,计算机使用了一个4字节的数来编址内存,这样可以对2^32块内存进行编址,每个块为1byte,2^32 byte = 4Gb,可以编址的内存大小为4G大小。
堆栈
堆栈提升
我们知道,在高级语言中,当我们执行一个函数调用,将会开辟一个新的栈空间,此时就需要进行堆栈提升,此时需要更改ESP和EBP寄存器中记录的栈底和栈底指针,这样函数中产生的值将不会影响原栈空间(黄色部分)的数据。右图为堆栈提升后的结果,此时push数据会从1005开始添加,pop也只能到1005这个地址的数据,无法再向下pop,这样将无法影响元堆栈的内容。
堆栈平衡
堆栈平衡实际上就是恢复堆栈内容,例如执行一次函数操作时,进行堆栈提升,开辟新的空间来供函数使用,当函数执行结束后,应该让栈底和栈顶指针恢复到原来的位置。
简述过程为
1.将ESP寄存器中的值,更改为EBP的值,这样栈顶到了目前栈底的位置。ESP=1005
2.将EBP寄存器指向的内存地址中的值取出,即1000,将EBP寄存器的值改为该值1000。这样EBP回到了1000的位置。
数据宽度
汇编语言中有三种数据宽度,分别为
-
BYTE:一个字节宽度,占8位
-
WORD:字,两个字节宽度,占16位
-
DOUBLEWORD:双字,四个字节宽度,占32位。
大小端模式
内存是从小到大进行编址的,储存一个多字节的数据时候,如果内存的小地址存储多字节数据的高位,就是大端模式。也就是说,先取数据的高位进行储存,再依次取低位储存。例如一个字符串"abcd",a为数据的高位,d为低位,内存会取出四个连续的内存空间来储存这个字符串。如果这段连续内存的小地址上储存的时a然后依次为bcd,就是大端模式。如果小地址处储存的是低位数据,则为小端模式。
数据储存为大端或者小端模式是由编译器决定的。