购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

3.5 80x86的寻址模式

寻址模式(addressing mode)是为了访问指令操作数而设置的特定于某种硬件的机制。80x86家族提供了3种不同类别的操作数:寄存器操作数、立即操作数及内存操作数。下面几节将讨论这些寻址模式。

3.5.1 80x86的寄存器寻址模式

80x86指令大都能够操作80x86的通用寄存器。可以将寄存器的名字作为指令操作数,以访问该寄存器。

我们用80x86的mov(“移动”)指令来看一些示例,了解汇编器是如何实现这种策略的。

3.5.1.1 HLA中的寄存器访问

HLA的mov指令看上去是这样的:

该指令将操作数 source 中的数据拷贝到操作数 destination 中。8位、16位和32位寄存器都可以作为该指令的有效操作数。对两个操作数的唯一限制就是要求其位数相同。

我们来看一些实际的80x86 mov指令:

请注意HLA只支持32位的80x86寄存器,而不支持64位寄存器集合。

3.5.1.2 Gas中的寄存器访问

Gas中的每个寄存器名要冠以百分号%,例如:

Gas的mov指令语法与HLA类似,只是不需要括号和分号,并且要求其汇编语句在源代码中不能跨行。例如:

3.5.1.3 MASM中的寄存器访问

MASM汇编器使用的寄存器名与HLA相同,且添加了对64位寄存器集合的支持:

MASM基本语法则类似于Gas,但源和目标操作数需要互换位置(互换位置这种做法符合标准的Intel语法规范)。也就是说,典型的mov指令是这样的:

这里有一些MASM语法的mov指令示例:

3.5.2 立即寻址模式

将寄存器和内存作为操作数的指令多数也能用立即数,即以常量为操作数。例如,HLA的下列mov指令将数值送入相应的目标寄存器:

采用立即寻址模式时,大部分汇编器都允许指定各种各样的文字常量类型。例如,可以提供十六进制、十进制或二进制形式的数;也可以提供字符常量作为操作数。原则是常量必须在目标操作数中放得下。

下面是一些HAL、Gas和MASM的例子,注意Gas要求在立即数前加$标识:

几乎每个汇编器都允许创建符号常量名,并将这些常量名当作源操作数。例如,HLA预定义了两个布尔常量true和false,我们可以将其作为mov指令的操作数:

某些汇编器甚至可用指针常量等抽象数据类型的常量,请参看对应汇编器的手册来了解其用法细节。

3.5.3 位移寻址模式

最常见且最易理解的32位寻址模式是位移(displacement-only)寻址模式,即直接(direct)寻址模式,其中通过32位常量指定内存单元的地址。内存单元可以是源操作数,也可以是目标操作数。请注意这种寻址模式只能在32位x86处理器上,或者在64位处理器的32位模式下使用。

举个例子,假设变量J是位于地址$8088的字节变量,则HLA指令“mov(J,al);”将位于内存地址$8088中的内容传送入寄存器AL中。类似地,如果字节变量K在内存中位于$1234,则指令“mov(dl,K);”将把寄存器DL中的内容传送到地址单元$1234中,请参看图3-4。

图3-4 位移寻址模式(直接寻址模式)

位移寻址模式非常适合于访问简单标量变量。高级语言程序中通常使用这种寻址模式访问静态变量或全局变量。

注意: Intel将这种寻址模式称作“位移寻址模式”,是因为操作码mov后面跟着32位常量的内存地址(即位移值)。在80x86处理器上,位移值是相对于内存开头位置(即地址0)的偏移量。

本章中的示例通常访问内存中的字节型数据。但也要知道,在80x86处理器上通过指定第一个字节的地址,同样可以访问字和双字,请参看图3-5。

图3-5 使用直接寻址模式(位移寻址模式)访问字或双字型数据

MASM和Gas对于位移寻址模式所采用的语法与HLA相同,即只要指定欲访问的变量名为操作数即可。有的MASM程序员爱用方括号括住变量名,尽管在这些汇编器中并无必要这么做。

下面是一些使用HLA、Gas和MASM语法的示例:

3.5.4 RIP相对寻址模式

x86-64 CPU在工作于64位模式时,不支持32位直接寻址模式。AMD工程师不想通过在指令末尾添加64位常量的办法来支持64位地址空间,而是创立了RIP相对寻址模式—对存放指令指针的RIP寄存器加上有符号32位常量来计算有效内存地址,以此代替直接寻址。这样就可以访问到当前指令前后2GB范围内的数据

3.5.5 寄存器间接寻址模式

80x86 CPU能够使用寄存器间接寻址模式,即通过寄存器间接访问内存。我们称这种模式为间接模式,是因为操作数本身并非地址,操作数的值才是要用的内存地址。在寄存器间接寻址模式中,寄存器的值指向要访问的内存地址。例如,HLA指令“mov(eax,[ebx]);”告诉CPU,将EAX中的内容保存到以EBX值为地址的内存单元中。

x86-64 CPU也支持64位模式下的寄存器间接寻址模式,通过使用如RAX,RBX,…,R15中的某个64位寄存器,寄存器间接寻址模式能够充分访问64位地址空间。例如,MASM指令mov eax,[rbx]告诉CPU,将从地址位于RBX寄存器里的内存单元内容调入EAX寄存器。

3.5.5.1 HLA的寄存器间接寻址模式

80x86的这种寻址模式有8个形式,使用HLA时是这样的:

这8个寻址形式以方括号内寄存器(分别为EAX、EBX、ECX、EDX、EDI、ESI、EBP或ESP)的内容作为偏移量,寻址到相应的内存单元。

注意: 寄存器间接寻址模式要求通过32位寄存器指定内存地址,在这种寻址模式下不能通过8位或16位寄存器指定内存地址。

3.5.5.2 MASM的寄存器间接寻址模式

MASM在32位寄存器间接寻址模式下的语法与HLA一模一样(但要记住MASM的指令操作数要反过来,只是寻址模式的语法相同)。在64位寄存器间接寻址模式下也是如此—用一对方括号括住寄存器名—只是要用64位寄存器,而非32位寄存器。

前面的HLA指令用MASM表示时等效为下面这样:

64位寄存器间接寻址模式的MASM示例如下:

3.5.5.3 Gas的寄存器间接寻址模式

Gas以圆括号括住寄存器名。前面32位HLA的mov指令的Gas形式如下:

64位寄存器间接寻址模式的Gas示例如下:

3.5.6 变址寻址模式

在所有地址运算完成后,指令终将访问的内存地址被称为有效地址(effective address)。变址寻址模式通过将变量地址—也被称为位移(displacement)或偏移(offset)—与方括号内的32位或64位寄存器值相加来计算有效地址,其和才是指令准备访问的内存地址。所以,如果 VarName 位于地址$1100,而EBX的内容为8,则HLA的“mov( VarName [ebx],al);”将会把地址单元$1108的内容放入寄存器AL,请参看图3-6。

x86-64 CPU也支持64位模式下的变址寻址模式。不过请注意,编码到指令中的偏移量依然是32位的。因此寄存器必须保存着基地址(简称为基址),而由偏移量提供要访问的内存单元自基地址的偏移。

图3-6 变址寻址模式

3.5.6.1 HLA的变址寻址模式

在HLA中采用下列变址寻址语法,其中 VarName 为程序中某个静态变量的名字。

3.5.6.2 MASM的变址寻址模式

MASM的32位语法与HLA相同,它还允许多种变址寻址的语法变形。下面是MASM支持的变形的等效形式:

由于加法满足交换率,MASM还允许其他很多组合。这些汇编器对待方括号内的并列项,就像它们被加号分隔一样。

这里给出的MASM语句等效于前面的HLA示例:

在64位模式下,MASM要求指定64位的寄存器名来实现变址寻址模式。此寄存器保存的是变量在内存里的基地址,编码到指令中的偏移量则是距此基地址的偏移。这意味着我们不能用寄存器作为全局数组的下标,数组下标通常可用RIP相对寻址模式。

下面是MASM在64位时的变址寻址模式例子:

3.5.6.3 Gas的变址寻址模式

和寄存器间接寻址模式相同,Gas在变址寻址模式中仍然用圆括号而非方括号。下面是Gas允许的变址寻址语法:

前面的HLA指令在Gas中等效为:

在64位模式下,Gas要求为变址寻址模式指定64位的寄存器名。其规则与MASM相同。下面是一些Gas的64位变址寻址模式示例:

3.5.7 比例变址寻址模式

比例变址寻址模式与变址寻址模式类似,区别只有两点。比例变址寻址模式还允许:

●将两个寄存器值相加,外加一个位移量。

●可将变址寄存器的值乘以比例因子1、2、4或8。

怎么做呢?请看下面的HLA例子:

比例变址寻址模式与变址寻址模式的主要差异在于它们有无“esi*4”。该示例通过将EBX加上4倍的ESI值来求得有效地址,图3-7给出了比例变址寻址模式的地址计算过程,其中 scale 指比例因子,在本例中 scale 等于4。

图3-7 比例变址寻址模式

在64位模式下,将基址寄存器和变址寄存器替换成64位寄存器即可。

3.5.7.1 HLA的比例变址寻址模式

HLA语法提供若干方式来指定使用比例变址寻址模式。这里有一些语法形式:

例子中的 BaseReg 32 表示任意32位通用寄存器, IndexReg 32 则表示除ESP外的任意32位通用寄存器, scale 必须是1、2、4、8中的某个常数,而 VarName 表示静态变量名, displacement 表示32位常量。

3.5.7.2 MASM的比例变址寻址模式

MASM支持的语法与HLA相同,但另有一些形式与变址寻址模式中给出的语法对应。这些形式只是基于加法交换率的语法变形。

MASM也支持64位的比例变址寻址模式,语法同32位的比例变址寻址模式,只是要改用64位寄存器名。32位比例变址寻址模式与64位比例变址寻址模式的主要区别在于,没有64位的disp[reg*index]寻址模式。在64位寻址模式下,对应的是PC相对变址寻址模式,偏移量是基于当前指令指针值的32位偏移。

3.5.7.3 Gas的比例变址寻址模式

Gas还是一如既往地使用圆括号而非方括号来括住比例变址操作数。Gas也使用3个操作数的语法来指定基址寄存器、变址寄存器和比例值,而不像其他汇编器那样用算术表达式给出这些值。Gas比例变址寻址模式的一般语法如下:

具体有以下形式:

scale 是1、2、4、8中的某个值。

Gas也支持64位的比例变址寻址模式,语法同32位的比例变址寻址模式,只是要改用64位寄存器名。使用64位寻址模式时,不能同时指定RIP相对寻址模式(如上例中的 VarName );只有32位的 displacement (偏移量)是合法的。 /n9yqt+xmiyY/1VlB06r22VLXyW4U4KYUxFpTcbRLil9kESvSYeYxU2qxDJjfL2m

点击中间区域
呼出菜单
上一章
目录
下一章
×