汇编 - 寄存器


处理器操作主要涉及处理数据。该数据可以存储在存储器中并从存储器中访问。然而,从内存中读取数据和将数据存储到内存中会减慢处理器的速度,因为它涉及通过控制总线发送数据请求并进入内存存储单元并通过同一通道获取数据的复杂过程。

为了加速处理器操作,处理器包括一些内部存储器存储位置,称为寄存器

寄存器存储用于处理的数据元素,而无需访问存储器。处理器芯片中内置了有限数量的寄存器。

处理器寄存器

IA-32 架构中有 10 个 32 位和 6 个 16 位处理器寄存器。寄存器分为三类 -

  • 通用寄存器,
  • 控制寄存器,以及
  • 段寄存器。

通用寄存器进一步分为以下几组 -

  • 数据寄存器,
  • 指针寄存器,以及
  • 索引寄存器。

数据寄存器

四个 32 位数据寄存器用于算术、逻辑和其他运算。这些 32 位寄存器可以通过三种方式使用 -

  • 作为完整的32位数据寄存器:EAX、EBX、ECX、EDX。

  • 32 位寄存器的下半部分可用作四个 16 位数据寄存器:AX、BX、CX 和 DX。

  • 上述4个16位寄存器的下半部和上半部可用作8个8位数据寄存器:AH、AL、BH、BL、CH、CL、DH和DL。

数据寄存器

其中一些数据寄存器在算术运算中具有特定用途。

AX 是主累加器;它用于输入/输出和大多数算术指令。例如,在乘法运算中,根据操作数的大小将一个操作数存储在EAX或AX或AL寄存器中。

BX 被称为基址寄存器,因为它可用于索引寻址。

CX被称为计数寄存器,与ECX一样,CX寄存器存储迭代操作中的循环计数。

DX被称为数据寄存器。它还用于输入/输出操作。它还与 AX 寄存器和 DX 一起使用,用于涉及大值的乘法和除法运算。

指针寄存器

指针寄存器是32位EIP、ESP和EBP寄存器以及相应的16位右部分IP、SP和BP。指针寄存器分为三类 -

  • 指令指针 (IP) - 16 位 IP 寄存器存储下一条要执行的指令的偏移地址。IP 与 CS 寄存器(如 CS:IP)关联给出了代码段中当前指令的完整地址。

  • 堆栈指针 (SP) - 16 位 SP 寄存器提供程序堆栈内的偏移值。SP 与 SS 寄存器 (SS:SP) 相关,指的是程序堆栈中数据或地址的当前位置。

  • 基址指针 (BP) - 16 位 BP 寄存器主要帮助引用传递给子例程的参数变量。SS寄存器中的地址与BP中的偏移量相结合,得到参数的位置。BP还可以与DI、SI组合作为基址寄存器进行特殊寻址。

指针寄存器

索引寄存器

32 位索引寄存器、ESI 和 EDI 及其 16 位最右边部分。SI和DI用于索引寻址,有时用于加法和减法。有两组索引指针 -

  • 源索引 (SI) - 它用作字符串操作的源索引。

  • 目标索引 (DI) - 它用作字符串操作的目标索引。

索引寄存器

控制寄存器

32 位指令指针寄存器和 32 位标志寄存器组合起来被视为控制寄存器。

许多指令涉及比较和数学计算并更改标志的状态,并且一些其他条件指令测试这些状态标志的值以将控制流带到其他位置。

常见的标志位有:

  • 溢出标志(OF) - 它表示有符号算术运算后数据的高位(最左边的位)溢出。

  • 方向标志 (DF) - 它确定移动或比较字符串数据的左或右方向。当DF值为0时,字符串操作采取从左到右的方向,当该值设置为1时,字符串操作采取从右到左的方向。

  • 中断标志(IF) - 它确定是否忽略或处理外部中断(如键盘输入等)。当该值为 0 时禁用外部中断,当设置为 1 时启用中断。

  • 陷阱标志 (TF) - 它允许将处理器的操作设置为单步模式。我们使用的 DEBUG 程序设置了陷阱标志,因此我们可以一次单步执行一条指令。

  • 符号标志 (SF) - 它显示算术运算结果的符号。该标志是根据算术运算之后的数据项的符号来设置的。符号由最左边位的高位表示。正结果将 SF 的值清除为 0,负结果将其设置为 1。

  • 零标志(ZF) - 它指示算术或比较运算的结果。非零结果将零标志清除为 0,零结果将其设置为 1。

  • 辅助进位标志 (AF) - 它包含算术运算后从位 3 到位 4 的进位;用于专门的算术。当 1 字节算术运算导致从位 3 进位到位 4 时,AF 被置位。

  • 奇偶校验标志 (PF) - 表示算术运算结果中 1 位的总数。偶数个 1 位将奇偶校验标志清除为 0,奇数个 1 位将奇偶校验标志设置为 1。

  • 进位标志 (CF) - 它包含算术运算后从高位(最左边)进位 0 或 1。它还存储移位循环操作的最后一位的内容。

下表列出了 16 位标志寄存器中标志位的位置:

旗帜: D 时间 S Z A C
位号: 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

段寄存器

段是程序中定义的用于包含数据、代码和堆栈的特定区域。主要分为三个部分 -

  • 代码段- 它包含所有要执行的指令。16位代码段寄存器或CS寄存器存储代码段的起始地址。

  • 数据段- 它包含数据、常量和工作区域。16位数据段寄存器或DS寄存器存储数据段的起始地址。

  • 堆栈段- 它包含过程或子例程的数据和返回地址。它被实现为“堆栈”数据结构。堆栈段寄存器或SS寄存器存储堆栈的起始地址。

除了 DS、CS 和 SS 寄存器外,还有其他额外段寄存器 - ES(额外段)、FS 和 GS,它们提供额外的段来存储数据。

在汇编编程中,程序需要访问内存位置。段内的所有内存位置都相对于段的起始地址。段从可被 16 或十六进制 10 整除的地址开始。因此,所有此类内存地址中最右边的十六进制数字是 0,通常不存储在段寄存器中。

段寄存器存储段的起始地址。为了获得段内数据或指令的准确位置,需要偏移值(或位移)。为了引用段中的任何内存位置,处理器将段寄存器中的段地址与该位置的偏移值组合起来。

例子

看下面的简单程序来了解寄存器在汇编编程中的使用。该程序在屏幕上显示 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
*********