汇编 - 寄存器(Registers)
处理器操作主要涉及处理数据。 该数据可以存储在存储器中并从其上访问。 然而,从存储器读取数据和将数据存储到存储器中会降低处理器的速度,因为它涉及通过控制总线向存储器存储单元发送数据请求并通过相同通道获取数据的复杂过程。
为了加速处理器操作,处理器包括一些内部存储器存储位置,称为registers 。
寄存器存储数据元素以便处理而无需访问存储器。 处理器芯片内置有限数量的寄存器。
处理器寄存器
IA-32架构中有10个32位和6个16位处理器寄存器。 寄存器分为三类 -
- General registers,
- 控制寄存器,和
- 段寄存器。
一般登记册进一步分为以下几组 -
- 数据寄存器,
- 指针寄存器,和
- 索引寄存器。
数据寄存器
四个32位数据寄存器用于算术,逻辑和其他操作。 这些32位寄存器可以三种方式使用 -
作为完整的32位数据寄存器:EAX,EBX,ECX,EDX。
32位寄存器的下半部分可用作4个16位数据寄存器:AX,BX,CX和DX。
上述四个16位寄存器的低半部分和高半部分可用作8个8位数据寄存器:AH,AL,BH,BL,CH,CL,DH和DL。
其中一些数据寄存器在算术运算中具有特定用途。
AX is the primary accumulator ; 它用于输入/输出和大多数算术指令。 例如,在乘法运算中,根据操作数的大小,一个操作数存储在EAX或AX或AL寄存器中。
BX is known as the base register ,因为它可以用于索引寻址。
CX is known as the count register ,因为ECX,CX寄存器在迭代操作中存储循环计数。
DX is known as the data register 。 它也用于输入/输出操作。 它还与AX寄存器以及DX一起用于涉及大值的乘法和除法运算。
指针寄存器
指针寄存器是32位EIP,ESP和EBP寄存器以及相应的16位右部分IP,SP和BP。 指针寄存器分为三类 -
Instruction Pointer (IP) - 16位IP寄存器存储下一条要执行的指令的偏移地址。 与CS寄存器相关联的IP(作为CS:IP)给出代码段中当前指令的完整地址。
Stack Pointer (SP) - 16位SP寄存器提供程序堆栈中的偏移值。 与SS寄存器(SS:SP)相关联的SP指的是程序堆栈内的数据或地址的当前位置。
Base Pointer (BP) - 16位BP寄存器主要用于引用传递给子程序的参数变量。 SS寄存器中的地址与BP中的偏移量组合以获得参数的位置。 BP也可以与DI和SI组合作为特殊寻址的基址寄存器。
索引寄存器
32位索引寄存器,ESI和EDI,以及它们最右边的16位部分。 SI和DI用于索引寻址,有时用于加法和减法。 有两组索引指针 -
Source Index (SI) - 用作字符串操作的源索引。
Destination Index (DI) - 用作字符串操作的目标索引。
控制寄存器
32位指令指针寄存器和32位标志寄存器组合被认为是控制寄存器。
许多指令涉及比较和数学计算,并且更改标志的状态,并且一些其他条件指令测试这些状态标志的值以将控制流程带到其他位置。
公共标志位是:
Overflow Flag (OF) - 表示在带符号算术运算后数据的高位(最左位)溢出。
Direction Flag (DF) - 它确定移动或比较字符串数据的左或右方向。 当DF值为0时,字符串操作采用从左到右的方向,当值设置为1时,字符串操作采用从右到左的方向。
Interrupt Flag (IF) - 它确定是否要忽略或处理键盘输入等外部中断。 它在值为0时禁用外部中断,在设置为1时启用中断。
Trap Flag (TF) - 它允许以单步模式设置处理器的操作。 我们使用的DEBUG程序设置了陷阱标志,因此我们可以一次执行一条指令。
Sign Flag (SF) - 它显示算术运算结果的符号。 根据算术运算后的数据项的符号设置该标志。 符号由最左边的位的高位表示。 正结果将SF的值清除为0,否定结果将其设置为1。
Zero Flag (ZF) - 它表示算术或比较运算的结果。 非零结果将零标志清除为0,零结果将其设置为1。
Auxiliary Carry Flag (AF) - 它包含算术运算后从第3位到第4位的进位; 用于专业算术。 当1字节算术运算导致从第3位进位到第4位时,AF置位。
Parity Flag (PF) - 它表示从算术运算获得的结果中的1位总数。 偶数个1位将奇偶校验标志清除为0,奇数个1位将奇偶校验标志设置为1。
Carry Flag (CF) - 在算术运算后,它包含来自高位(最左边)的0或1的进位。 它还存储shift或rotate操作的最后一位的内容。
下表显示了16位Flags寄存器中标志位的位置:
旗: | O | D | I | T | S | Z | A | P | C | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
位号: | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
细分寄存器
段是在程序中定义的用于包含数据,代码和堆栈的特定区域。 主要有三个部分 -
Code Segment - 它包含要执行的所有指令。 16位代码段寄存器或CS寄存器存储代码段的起始地址。
Data Segment - 它包含数据,常量和工作区域。 16位数据段寄存器或DS寄存器存储数据段的起始地址。
Stack Segment - 它包含过程或子例程的数据和返回地址。 它被实现为“堆栈”数据结构。 堆栈段寄存器或SS寄存器存储堆栈的起始地址。
除DS,CS和SS寄存器外,还有其他额外的段寄存器 - ES(额外段),FS和GS,它们提供用于存储数据的附加段。
在汇编编程中,程序需要访问存储器位置。 段内的所有存储器位置都相对于段的起始地址。 段开始于可被16或十六进制10整除的地址。因此,所有这些存储器地址中最右边的十六进制数字是0,通常不存储在段寄存器中。
段寄存器存储段的起始地址。 要获得段内数据或指令的确切位置,需要偏移值(或位移)。 为了引用段中的任何存储器位置,处理器将段寄存器中的段地址与位置的偏移值组合。
例子 (Example)
查看以下简单程序,了解汇编编程中寄存器的使用。 该程序在屏幕上显示9颗星以及一条简单的信息 -
section .text
global _start ;must be declared for linker (gcc)
_start: ;tell linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov edx,9 ;message length
mov ecx,s2 ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Displaying 9 stars',0xa ;a message
len equ $ - msg ;length of message
s2 times 9 db '*'
编译并执行上述代码时,会产生以下结果 -
Displaying 9 stars
*********