汇编语言中的寄存器详解
汇编语言中的寄存器详解
汇编语言是计算机科学中的重要基础,而寄存器作为处理器内部的重要存储单元,对程序的执行效率有着至关重要的影响。本文将详细介绍IA-32架构中的寄存器类型及其功能,并通过一个简单的汇编程序实例展示寄存器的使用方法。
处理器操作主要涉及处理数据。这些数据可以存储在内存中并从内存中访问。然而,从存储器中读取数据并将数据存储到存储器中会减慢处理器的速度,因为它涉及复杂的过程,即通过控制总线将数据请求发送到存储器存储单元,然后通过同一通道获取数据。
为了加速处理器的操作,处理器包括一些内部内存存储位置,称为寄存器。
寄存器存储用于处理的数据元素,而无需访问内存。处理器芯片内置有限数量的寄存器。
处理器寄存器
IA-32体系结构中有10个 32 位和6个 16 位处理器寄存器。
存器分为三类:
- 通用寄存器
- 控制寄存器
- 段寄存器
通用寄存器进一步分为以下几类:
- 数据寄存器
- 指针寄存器
- 索引寄存器
- 数据寄存器
数据寄存器
4个32位数据寄存器用于算术、逻辑和其他操作。这些32位寄存器可以用3种方式使用:
- 作为完整的 32 位数据寄存器:EAX、EBX、ECX、EDX。
- 32 位寄存器的下半部分可以用作 4 个 16 位数据寄存器:AX、BX、CX和DX。
- 上述四个 16 位寄存器的下半部和上半部可以用作八个 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寄存器存储要执行的下一条指令的偏移地址。与 CS 寄存器关联的 IP(作为 CS:IP)给出了代码段中当前指令的完整地址。
- 堆栈指针(SP)-16 位SP寄存器提供程序堆栈内的偏移值。与 SS 寄存器(SS:SP)关联的 SP 是指程序堆栈中数据或地址的当前位置。
- 基本指针(BP)-16 位BP寄存器主要帮助参考传递给子例程的参数变量。SS 寄存器中的地址与 BP 中的偏移量相结合,以获取参数的位置。BP 也可以与 DI 和 SI 组合用作特殊寻址的基址寄存器。
索引寄存器
32 位索引寄存器ESI和EDI及其最右边的 16 位部分。SI和DI用于索引寻址,有时用于加法和减法。
索引指针分为两种:
- 源索引(SI) -用作字符串操作的源索引。
- 目标索引(DI) -用作字符串操作的目标索引。
控制寄存器
将 32 位指令指针寄存器和 32 位标志寄存器组合起来视为控制寄存器。许多指令涉及比较和数学计算,并更改标志的状态,而其他一些条件指令则测试这些状态标志的值,以将控制流带到其他位置。
通用标志位是:
- 溢出标志(OF):指示有符号算术运算后数据的高阶位(最左位)的溢出。
- 方向标记(DF):它确定向左或向右移动或比较字符串数据的方向。DF值为 0 时,字符串操作为从左至右的方向;当DF值为 1 时,字符串操作为从右至左的方向。
- 中断标志(IF):确定是否忽略或处理外部中断(例如键盘输入等)。当值为 0 时,它禁用外部中断,而当值为 1 时,它使能中断。
- 陷阱标志(TF):允许在单步模式下设置处理器的操作。我们使用的
DEBUG
程序设置了陷阱标志,因此我们可以一次逐步执行一条指令。 - 符号标志(SF):显示算术运算结果的符号。根据算术运算后数据项的符号设置此标志。该符号由最左位的高位指示。正结果将SF的值清除为 0,负结果将其设置为 1。
- 零标志(ZF):指示算术或比较运算的结果。非零结果将零标志清零,零结果将其清零。
- 辅助进位标志(AF):包含经过算术运算后从位 3 到位 4 的进位;用于专业算术。当1字节算术运算引起从第 3 位到第 4 位的进位时,将设置AF。
- 奇偶校验标志(PF):指示从算术运算获得的结果中 1 位的总数。偶数个 1 位将奇偶校验标志清为 0,奇数个 1 位将奇偶校验标志清为 1。
- 进位标志(CF):在算术运算后,它包含一个高位(最左边)的 0 或 1 进位。它还存储移位或旋转操作的最后一位的内容。
下表列出了 16 位标志寄存器中标志位的位置:
标志 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
段寄存器
段是程序中定义的特定区域,用于包含数据,代码和堆栈。有 3 个主要部分:
- 代码段:它包含所有要执行的指令。16 位代码段寄存器或 CS 寄存器存储代码段的起始地址。
- 数据段:它包含数据,常量和工作区。16 位数据段寄存器或 DS 寄存器存储数据段的起始地址。
- 堆栈段:它包含数据或过程或子例程的返回地址。它被实现为 "堆栈" 数据结构。堆栈段寄存器或 SS 寄存器存储堆栈的起始地址。
除了 DS,CS 和 SS 寄存器外,还有其他段寄存器 -ES(额外段),FS和GS,它们提供了用于存储数据的其他段。在汇编语言中,程序需要访问存储器位置。段中的所有存储位置都相对于段的起始地址。段的起始地址可以是 16 或十六进制的整数,因此,所有此类存储地址中最右边的十六进制数字为 0,通常不存储在段寄存器中。
段寄存器存储段的起始地址。为了获得数据或指令在段中的确切位置,需要一个偏移值(或位移)。为了引用段中的任何存储位置,处理器将段寄存器中的段地址与该位置的偏移值进行组合。
实例
查看以下简单程序,以了解汇编程序中寄存器的使用。
该程序在屏幕上显示 9 个星星以及一条简单消息:
1.
section .text
2.
global _start ;必须声明链接器(gcc)
3.
4.
_start: ;告诉链接器入口点
5.
mov edx,len ;消息长度
6.
mov ecx,msg ;消息内容
7.
mov ebx,1 ;文件描述 (stdout)
8.
mov eax,4 ;系统调用编号 (sys_write)
9.
int 0x80 ;调用内核
10.
11.
mov edx,9 ;消息长度
12.
mov ecx,s2 ;消息内容
13.
mov ebx,1 ;文件描述 (stdout)
14.
mov eax,4 ;系统调用编号 (sys_write)
15.
int 0x80 ;调用内核
16.
17.
mov eax,1 ;系统调用编号 (sys_write)
18.
int 0x80 ;调用内核
19.
20.
section .data
21.
msg db 'Displaying 9 stars',0xa ;消息内容
22.
len equ $ - msg ;消息长度
23.
s2 times 9 db '*'
运行一下
结果如下:
1.
Displaying 9 stars
2.
*********