汇编语言基础:寄存器和寻址方式


1. 寄存器

以16位8086构架为主说下寄存器的名称和用途,并在16位基础上说明一下32位、64位的寄存器。

寄存器分类

  • 通用寄存器
    • 数据寄存器(AX,BX,CX,DX)
    • 指针寄存器(SP,BP)
    • 索引寄存器(SI,DI)
  • 段寄存器(CS,DS,SS,ES)
  • 控制寄存器
    • 指令指针寄存器(IP)
    • 标志寄存器(FLAG)

16位的8086处理器共14个寄存器。32位和64位的x86,x64构架分别对寄存器进行了扩充。

1.1 通用寄存器

通用寄存器虽然分为了三类,但是实际上对于比较新的cpu这些寄存器功能都差不多,RISC等构架通用寄存器就是直接采用数字编号的,没有再细分功能。
当然习惯上还是把不同寄存器用于不同的用途,这也是ABI的一个重要部分。比如通常默认AX就是函数返回值,有的系统默认优先把SI,DI作为函数参数。

1.1.1 数据寄存器

AX、BX、CX、DX 一般用来存放数据,所以被称为数据寄存器。

  • AX(Accumulator Register) :累加寄存器,主要用于输入/输出和大规模的指令运算。常用于四则运算,函数返回值等。
  • BX(Base Register):基址寄存器,常用于在相对寻址(基址+偏移,见本文后续章节)中存储基址(基础访问地址)。也常用于四则运算。
  • CX(Count Register):计数寄存器,CX 寄存器在迭代的操作中会循环计数。
  • DX(Data Register):数据寄存器,也用于输入/输出操作。还与AX寄存器一起使用,用于涉及大数值的乘法和除法运算。

现代CPU的AX,BX,CX,DX几个寄存器在功能并无区别,最常见的用途是存储操作数,函数参数和运算结果等信息。
比如通常函数返回值默认都保存在AX中。

8位寄存器

AX,BX,CX,DX在8086中为16位寄存器,每个寄存器的高位和低位均可以作为8位寄存器访问。

  • AX寄存器可以分为两个独立的8位的AH和AL寄存器
  • BX寄存器可以分为两个独立的8位的BH和BL寄存器
  • CX寄存器可以分为两个独立的8位的CH和CL寄存器
  • DX寄存器可以分为两个独立的8位的DH和DL寄存器

寄存器名称通常不区分大小写,汇编语言中通常ax,bx,cx,dx和AX,BX,CX,DX相同。

x32构架

x32架构中,通用寄存器都在16位版本的基础上扩展成为32位版本,名字加了E作为前缀。

  • EAX(低位为AX):通用寄存器
  • EBX(低位为BX):通用寄存器
  • ECX(低位为CX):通用寄存器
  • EDX(低位为DX):通用寄存器

为了兼容16位模式程序,访问AX,BX,CX,DX相当于访问32位寄存器的低16位,32位寄存器的高16位不可单独访问。

x64构架

在x64架构中,通用寄存器都扩展成为64位版本,名字也进行了升级。

  • RAX, RBX, RCX, RDX
  • R8-R15:x64架构引入的8个新的通用寄存器

为了兼容32位模式程序,使用上面的名字仍然是可以访问的,相当于访问64位寄存器的低32位。高位32位模式不可访问。

1.1.2 指针寄存器(Pointer Register)

  • SP(Stack Pointer):栈指针,栈顶指针,只能访问栈顶。
  • BP(Base Pointer):基础指针,栈寄存器上的偏移量,用来定位栈上变量。用它可直接存取堆栈中的数据。

指针寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。

  • x32构架下指针寄存器名称为ESP,EBP。是32位通用寄存器。低位可以用SP,BP访问。
  • x64构架下指针寄存器名称为RSP,RBP。是64位通用寄存器。低位可以用ESP,EBP访问。

1.1.3 索引(变址)寄存器

  • SI(Source Index):源索引寄存器。变址寄存器。常用于在变址寻址(基址+变址,见本文后续章节)中存储变址,也常用来拷贝源字符串。
  • DI(Destination Index):目的索引寄存器。目标变址寄存器。常用于在变址寻址(基址+变址,见本文后续章节)中存储变址。也常用来复制到目标字符串。

SI和DI功能和BX相同,可以用于间接寻址。主要用于存放存储单元在段内的偏移量。但是SI、DI不可分割成8位寄存器。

SI和DI两个经常搭配一起使用,执行字符串的复制等操作。有的系统默认优先把SI,DI作为函数参数。

  • x32构架下指针寄存器名称为ESI,EDI。低位地址分别对应SI和DI。
  • x64构架下指针寄存器名称为RSI,RDI。低位地址分别对应ESI和EDI。

1.2 段寄存器

在16为构架中,16位的指针只能访问64k的内存,为了访问更多的内存,使用段寄存器和指针配合访问内存地址。(x32,x64都采用段寄存器+指针地址方式访问内存)。

x86构架cpu,所有内存地址都是段地址+偏移方式引用。cpu内部根据段地址和偏移地址计算物理地址。
16位系统中物理地址=段地址*16+偏移地址 通常写作段寄存器:偏移

  • CS(Code Segment):代码段寄存器。CS:IP表示要执行代码的内存地址。
  • DS(Data Segment):数据段寄存器。DS:偏移量是数据的内存地址。
  • SS(Stack Segment):栈段寄存器。SS:SP是栈顶内存地址。
  • ES(Extra Segment):扩展段寄存器。扩展的数据段寄存器。

计算机启动后会自动找到地址CS:IP地址的指令代码运行,运行后IP自动偏移下一个指令。
数据地址默认段寄存器为DS。栈默认段寄存器为SS。

x32和x64构架段寄存器名称未变,但是扩展了两个寄存器。

  • FS(Extra Segment):数据段寄存器。扩展的数据段寄存器。
  • GS(Extra Segment):数据段寄存器。扩展的数据段寄存器。

1.3 控制寄存器

  • IP(Instruction Pointer):指令指针。是存放下次将要执行的指令在代码段的偏移量。即CS:IP执行下一条要执行的命令。

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

  • 64位CPU把指令指针扩展到64位,并记作RIP。RIP的低16位与EIP作用相同。

在具有预取指令功能的系统中,下次要执行的指令通常已被预取到指令队列中,除非发生转移情况。

2. 寄存器寻址

  • cpu执行的指令只有一种寻址方式,即CS:IP。(x32上地址为CS:EIP,x64上地址为CS:RIP
  • 数据也就是指令的操作数有七种寻址方式。
    • 立即寻址:立即数
    • 寄存器寻址:寄存器中的数
    • 内存寻址(根据段地址和给定地址找到数据)
      • 直接寻址:直接指定地址
      • 间接寻址:寄存器中指定地址
      • 相对寻址:寄存器中地址+偏移量
      • 变址寻址:寄存器中地址+变址寄存器中地址
      • 相对变址寻址:寄存器中地址+变址寄存器中地址+偏移量

2.1 立即数

常数实际上是直接放在代码中的,会在加载指令的时候,自动找到。

mov AX,80h   ; 80h就被称为立即数

2.2 寄存器寻址

数据存储在寄存器中,直接用寄存器名称调用。

mov AX,BX

寄存器寻址速度非常快。数据在寄存器中,所以不存在段地址。

2.3 内存寻址

2.3.1 直接寻址(指令中硬编码地址)

操作数存放在内存中,地址在指令中直接给出。

mov AX,[123H]

数据段的段寄存器默认为DS。

如果要指定访问其它段内的数据,可在指令中用段前缀的方式显式地书写出来。

mov BX,ES:[123H]

2.3.2 间接寻址(地址指针)

操作数在内存中,地址用SI、DI、BX和BP等寄存器之一来指定。

mov BX,[di]
mov AX,[si]

地址用SI、DI和BX等指定时,缺省的段寄存器为DS;
地址用BP来指定时,缺省的段寄存器为SS(即:堆栈段)。

2.3.3 相对寻址(基址+偏移)

操作数在内存中,地址是一个基址寄存器(BX、BP)或变址寄存器(SI、DI)的内容和一个偏移量之和。

mov BX,[si+100H]

若地址用SI、DI、BX等加偏移量计算,缺省的段寄存器为DS;
若地址用BP加偏移量计算,缺省的段寄存器为SS。

2.3.4 变址寻址(基址+变址)

操作数在内存中,地址是一个基址寄存器(BX、BP)和一个变址寄存器(SI、DI)的内容之和。

mov BX,[BX+SI]
  • 基址寄存器为BX,缺省的段寄存器为DS。
  • 基址寄存器为BP,缺省的段寄存器为SS。

2.3.5 相对变址寻址(基址+变址+偏移)

操作数在内存中,地址是一个基址寄存器(BX、BP)的值、一个变址寄存器(SI、DI)的值和一个偏移量之和。

mov AX,[BX+si+200H]   ;mov AX,200h[BX][si]或者mov AX,200h[si][BX]也是对的,多种写法
  • 基址寄存器为BX,缺省的段寄存器为DS。
  • 基址寄存器为BP,缺省的段寄存器为SS。


持续更新及修订中。

未经允许请勿转载。

猜你喜欢

转载自blog.csdn.net/hustlei/article/details/125140168