汇编自学(二)

上一篇博客:自学汇编(一) 寄存器  

今天学习的内容是各类操作数寻址方式。

前言

CPU中除了有这些可以用于数据运算的寄存器外,还需要与外界的内存间进行数据交换,这里的过程被称为操作数寻址,寻址即为寻找某个数据在内存里的地址,然后把该数据调入寄存器中或与汇编指令间进行运算。操作数是指令或程序的主要处理对象。如果某条指令或某个程序不处理任何操作数,那么该指令或程序不可能有数据处理功能。在 CPU 的指令系统中.除 NOP (空操作指令), HLT (停机指令)等少数指令之外,大量的指令在执行过程中都会涉及到操作数。所以,在指令中如何表达操作数或操作数所在位置就是正确运用汇编指令的一个重要因素。操作数对于一个汇编指令来说,就是这个指令的参数.

在指令中,指定操作数或操作数存放位置的方法称为寻址方式。操作数的各种寻址方式是用汇编语言进行程序设计的基础。微机系统有七种基本的寻址方式: 立即寻址方式 、 寄存器寻址方式 、 直接寻址方式 、 寄存器间接寻址方式 、 寄存器相对寻址方式 、 基址加变址寻址方式 、 相对基址加变址寻址方式 等。其中,后五种寻址方式是确定内存单元有效地址的五种不同的计算方法,用它们可方便地实现对数组元素的访问。另外,在32位微机系统中,为了扩大对存储单元的寻址能力,增加了一种新的寻址方式—— 32位地址的寻址方式 。

为了表达方便,我们用符号“( X )”表示X的值,如:( AX )表示寄存器 AX 的值。

立即数寻址

操作数作为指令的一部分而直接写在指令中,这种操作数称为立即数,这种寻址方式也就称为立即数寻址方式。

立即数可以是8位、16位或32位,该数值紧跟在操作码之后。例如:

MOV AH, 80H   ADD AX, 1234H   MOV ECX, 123456H
MOV AH, 12H   MOV AX, 3456H    ADD ECX, 32123456H

其中:AH、AX和ECX分别为8位字节型、16位短整数型和32位整数型。

MOV 指令是把操作数2赋值给操作数1这个存储单元,即 操作数1=操作数2.

ADD 指令是把操作数1与操作数2相加后存储在操作数1里,即 操作数1=操作数1+操作数2

以上指令中的第二操作数都是立即数,在汇编语言中,规定:立即数不能作为指令中的第一操作数。如 mov 80H,AH 是不允许的.

立即数寻址方式通常用于对通用寄存器或内存单元赋初值。如下图是指令“MOV AX, 4576H”存储形式和执行示意图。

                                                                      

                                                         立即寻址方式的存储和执行示意图

寄存器寻址

指令所要的操作数已存储在某寄存器中,或把目标操作数存入寄存器.把在指令中指出所使用寄存器(即:寄存器的助忆符)的寻址方式称为寄存器寻址方式。

指令中可以引用的寄存器及其符号名称如下:

  8 位寄存器有:AH、AL、BH、BL、CH、CL、DH、DL等;
  16位寄存器有:AX、BX、CX、DX 等.虽然还有SI、DI、SP、BP、段寄存器,但这几个在32位程序里一般不用;
  32位寄存器有:EAX、EBX、ECX、EDX、ESI、EDI、ESP和EBP等。

寄存器寻址方式是一种简单快捷的寻址方式,源和目的操作数都可以是寄存器。

1、源操作数2是寄存器寻址方式,目的操作数1为内存地址

如:ADD dword [ECX], EAX  ADD word [EBX], AX   MOV byte [4098], BH 等。

其中:EAX、CX和CL是32位整数型,16位短整数型和8位字节型的内存地址变量。

2、目的操作数是寄存器寻址方式

如:ADD BH, 78h    ADD AX, 1234h   mov EBX, dword ptr [4098] 等。

3、源和目的操作数都是寄存器寻址方式

如:MOV EAX, EBX   MOV AX, BX     MOV DH, BL等。

由于指令所需的操作数已存储在寄存器中,或操作的结果存入寄存器,这样,在指令执行过程中,会减少读/写存储器单元的次数,所以,使用寄存器寻址方式的指令具有较快的执行速度。通常情况下,我们提倡在编写汇编语言程序时,应尽可能地使用寄存器寻址方式,但也不要把它绝对化。

需要注意的是某个操作数若是用 [ ] 中括号括住的就说明这个操作数是内存地址,另外一条指令里不能同时有两个操作数都是内存地址 如 mov [eax],[ecx]   mov [4096],[eax] 等是不允许的

直接寻址方式

指令所要的操作数存放在内存中,在指令中直接给出该操作数的有效地址,这种寻址方式为直接寻址方式。

在通常情况下,操作数存放在数据段中,所以,其物理地址将由数据段寄存器 DS 和指令中给出的有效地址直接形成,但如果使用段超越前缀,那么,操作数可存放在其它段。

假设有指令:MOV BX, [1234H],在执行时,(DS)=2000H,内存单元21234H的值为5213H。问该指令执行后,BX的值是什么?

解:根据直接寻址方式的寻址规则,把该指令的具体执行过程用右图来表示。

从图中可看出执行该指令要分三部分:

 

                            直接寻址方式的存储和执行示意图

由于1234H是一个直接地址,它紧跟在指令的操作码之后,随取指令而被读出;

访问数据段的段寄存器是 DS ,所以,用 DS 的值和偏移量1234H相加,得存储单元的物理地址:21234H;

取单元21234H的值5213H,并按“高高低低”的原则存入寄存器BX中。

所以,在执行该指令后,BX的值就为5213H。

由于数据段的段寄存器默认为 DS ,如果要指定访问其它段内的数据,可在指令中用 段前缀的方式 显式地书写出来。

下面指令的目标操作数就是带有段前缀的直接寻址方式。

MOV  ES :[1000H], AX

直接寻址方式常用于处理内存单元的数据,其操作数是内存变量的值,该寻址方式可在 64K 字节的段内进行寻址。

注意:立即寻址方式和直接寻址方式的书写格式的不同,直接寻址的地址要写在括号“[”,“]”内。在程序中,直接地址通常用内存变量名来表示,如:MOV BX, VARW,其中, VARW 是内存字变量。

试比较下列指令中源操作数的寻址方式(VARW是内存字变量):

寻址方式比较

MOV AX, 1234H

MOV AX, [1234H]

;前者是立即寻址,后者是直接寻址

MOV AX, VARW

MOV AX, [VARW]

;两者是等效的,均为直接寻址

寄存器间接寻址

操作数在存储器中,操作数的有效地址用 SI 、 DI 、 BX 和 BP 等四个寄存器之一来指定,称这种寻址方式为寄存器间接寻址方式。该寻址方式物理地址的计算方法如下:

 

寄存器间接寻址方式读取存储单元的原理如图所示。

 

读取操作数过程的示意图

在不使用段超越前缀的情况下,有下列规定:

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

假设有指令:MOV BX,[DI],在执行时,(DS)=1000H,(DI)=2345H,存储单元12345H的内容是4354H。问执行指令后,BX的值是什么?

解:根据寄存器间接寻址方式的规则,在执行本例指令时,寄存器 DI 的值不是操作数,而是操作数的地址。该操作数的物理地址应由 DS 和 DI 的值形成,即:

PA=(DS)*16+DI=1000H*16+2345H=12345H。

所以,该指令的执行效果是:把从物理地址为12345H开始的一个字的值传送给 BX 。

其执行过程如右图所示。

 

读取操作数过程的示意图

寄存器相对寻址

指令中给出的8位/16位偏移量用补码表示。在计算有效地址时,如果偏移量是8位,则进行符号扩展成16位。当所得的有效地址超过 0FFFFH ,则取其 64K 的模。

假设指令:MOV BX, [SI+100H],在执行它时,(DS)=1000H,(SI)=2345H,内存单元12445H的内容为2715H,问该指令执行后,BX的值是什么?

基址加变址寻址方式

在不使用段超越前缀的情况下,规定:如果有效地址中含有 BP ,则缺省的段寄存器为 SS ;否则,缺省的段寄存器为 DS 。

假设指令:MOV BX, [BX+SI],在执行时,(DS)=1000H,(BX)=2100H,(SI)=0011H,内存单元12111H的内容为1234H。问该指令执行后,BX的值是什么?

操作数在存储器中,其有效地址是一个基址寄存器( BX 、 BP )或变址寄存器( SI 、 DI )的内容和指令中的8位/16位偏移量之和。其有效地址的计算公式如下式所示。

在不使用段超越前缀的情况下有下列规定:

  • 若有效地址用 SI 、 DI 和 BX 等之一来指定,则其缺省的段寄存器为 DS 。
  • 若有效地址用 BP 来指定,则其缺省的段寄存器为 SS 。

相对基址加变址寻址方式

操作数在存储器中,其有效地址是一个基址寄存器( BX 、 BP )的值、一个变址寄存器( SI 、 DI )的值和指令中的8位/16位偏移量之和。其有效地址的计算公式如右式所示。

在不使用段超越前缀的情况下,规定:如果有效地址中含有 BP ,则其缺省的段寄存器为 SS ;否则,其缺省的段寄存器为 DS 。

指令中给出的8位/16位偏移量用补码表示。在计算有效地址时,如果偏移量是8位,则进行符号扩展成16位。当所得的有效地址超过 0FFFFH ,则取其 64K 的模。

假设指令:MOV AX, [BX+SI+200H],在执行时,(DS)=1000H,(BX)=2100H,(SI)=0010H,内存单元12310H的内容为1234H。问该指令执行后,AX的值是什么?

 

解:根据寄存器相对寻址方式的规则,在执行本例指令时,源操作数的有效地址 EA 为:

 

寄存器相对寻址方式的执行过程示意图

比如:用 D1[i] 来访问一维数组 D1 的第 i 个元素,它的寻址有一个自由度,用 D2[i][j] 来访问二维数组 D2 的第 i 行、第 j 列的元素,其寻址有二个自由度。多一个可变的量,其寻址方式的灵活度也就相应提高了。

相对基址加变址寻址方式有多种等价的书写方式,下面的书写格式都是正确的,并且其寻址含义也是一致的。

MOV AX, [BX+SI+1000H]   MOV AX, 1000H[BX+SI]
MOV AX, 1000H[BX][SI]        MOV AX, 1000H[SI][BX]

但书写格式BX [1000+SI]和SI[1000H+BX]等是错误的,即所用寄存器不能在“[“,”]”之外,该限制对寄存器相对寻址方式的书写也同样起作用。

相对基址加变址寻址方式是以上7种寻址方式中最复杂的一种寻址方式,它可变形为其它类型的存储器寻址方式。表3.1列举出该寻址方式与其它寻址方式之间的变形关系。

相对基址加变址寻址方式与其它寻址方式之间的变形关系

操作数在存储器中,其有效地址是一个基址寄存器( BX 、 BP )和一个变址寄存器( SI 、 DI )的内容之和。其有效地址的计算公式如右式所示。

 

解:根据基址加变址寻址方式的规则,在执行本例指令时,源操作数的有效地址 EA 为:

EA =(BX)+(SI)=2100H+0011H=2111H

该操作数的物理地址应由 DS 和 EA 的值形成,即:

PA =(DS)*16+ EA =1000H*16+2111H=12111H

所以,该指令的执行效果是:把从物理地址为12111H开始的一个字的值传送给 BX 。

其执行过程如右图所示。

 

 

基址加变址寻址方式的执行过程示意图

 

解:根据相对基址加变址寻址方式的规则,在执行本例指令时,源操作数的有效地址 EA 为:

EA =(BX)+(SI)+200H=2100H+0010H+200H=2310H

该操作数的物理地址应由 DS 和 EA 的值形成,即:

PA =(DS)*16+EA=1000H*16+2310H=12310H

所以,该指令的执行效果是:把从物理地址为12310H开始的一个字的值传送给 AX 。其执行过程如右图所示。

从相对基址加变址这种寻址方式来看,由于它的可变因素较多,看起来就显得复杂些,但正因为其可变因素多,它的灵活性也就很高。

 

相对基址加变址寻址方式的执行过程示意图

源操作数

指令的变形

源操作数的寻址方式

只有偏移量

MOV AX, [100H]

直接寻址方式

只有一个寄存器

MOV AX, [BX] 或 MOV AX, [SI]

寄存器间接寻址方式

有一个寄存器和偏移量

MOV AX, [BX+100H] 或 MOV AX, [SI+100H]

寄存器相对寻址方式

有二个寄存器

MOV AX, [BX+SI]

基址加变址寻址方式

有二个寄存器和偏移量

MOV AX, [BX+SI+100H]

相对基址加变址寻址方式

32位地址的寻址方式

在32位微机系统中,除了支持前面的七种寻址方式外,又提供了一种更灵活、方便,但也更复杂的内存寻址方式,从而使内存地址的寻址范围得到了进一步扩大。

在用16位寄存器来访问存储单元时,只能使用基地址寄存器( BX 和 BP )和变址寄存器( SI 和 DI )来作为地址偏移量的一部分,但在用32位寄存器寻址时,不存在上述限制,所有32位寄存器( EAX 、 EBX 、 ECX 、 EDX 、 ESI 、 EDI 、 EBP 和 ESP )都可以是地址偏移量的一个组成部分。

当用32位地址偏移量进行寻址时,内存地址的偏移量可分为三部分:一个32位基址寄存器,一个可乘1、2、4或8的32位变址寄存器,一个8位/32位的偏移常量,并且这三部分还可进行任意组合,省去其中之一或之二。

32位基址寄存器是:EAX、EBX、ECX、EDX、ESI、EDI、EBP和ESP;
32位变址寄存器是:EAX、EBX、ECX、EDX、ESI、EDI和EBP(除 ESP 之外)。

如:[ EBX + EBP ]中的 EBX 是基址寄存器, EBP 是变址寄存器,而[ EBP + EBX ]中的 EBP 是基址寄存器, EBX 是变址寄存器;

2、默认段寄存器的选用取决于基址寄存器;

3、基址寄存器是 EBP 或 ESP 时,默认的段寄存器是 SS ,否则,默认的段寄存器是 DS ;

4、在指令中,如果使用段前缀的方式,那么,显式段寄存器优先。

总结

寻址就是指内存地址.只要使用中括号 [ ] 括住的操作数说明该操作数为内存地址,每条汇编指令里不能同时有两个操作数都是[]括住的内存地址。

除非有[]的内存地址操作数外,其它方式的寻址一般都不必深究,无非都是这个寄存器与那个寄存器之间的运算与赋值而已。

对于立即数的值已经被包含在了整条指令中,更不必管它,只要不在操作数1里使用无中括号的立即数就行了。

内存地址可以进行条件运行,如 [eax+ecx]    [ebx+2+edx]   [ecx*2+eax-4] 这类里面有加减乘的运算式都是合法的。

 

下一节学习一下汇编指令。

发布了66 篇原创文章 · 获赞 230 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/lyztyycode/article/details/97382038