[转载]操作数的寻址方式

寻址方式就是在汇编语言程序中寻找操作数或操作数地址的各种方法。

8086提供了与操作数有关和与I/O端口地址有关的两类寻址方式。

操作数有关的寻址方式有七种,分别是:1)立即寻址,2)寄存器寻址,3)直接寻址,4)寄存器间接寻址,5)寄存器相对寻址,6)基址加变址寻址,7)相对基址加变址寻址,8)基址变址比例相对寻址;

I/0端口有关的寻址方式有1)直接端口寻址和2)间接端口寻址方式。

1. 立即寻址

立即(Immediate)寻址,就是在指令中使用的操作数是常数,这个常数(即立即数)就包含在指令中。

  MOV AX,2345H
  
MOV AL,0EH

2. 寄存器寻址 

寄存器(Register)寻址方式的操作数在CPU内部的寄存器中。使用寄存器寻址,CPU不用访问内存就可以取得或修改操作数。 

    MOV BL,80       ;目标操作数BL是寄存器寻址
    MOV EAX,EBX     ;源操作数EBX和目标操作数EAX都是寄存器寻址

3. 直接寻址

除了立即寻址和寄存器寻址方式外,其他的几种寻址方式的操作数都在内存单元中,寻址方式要说明的是CPU如何确定内存操作数的地址,然后CPU再对该内存单元中的操作数进行处理。直接寻址(Direct)寻址就是指令中直接给出了操作数的地址。指令中使用变量时,就是直接寻址。

    MOV EAX,dVal
    
MOV dVal,EBX

在翻译成机器指令后,变量是用它的地址而不是它的名字来表示的。地址外面加一对方括号,表示取这个地址中的内容。

00401010 A1 11 40 40 00       MOV EAX,[00404011]
00401015 89 1D 11 40 40 00    MOV [00404011],EBX

CPU在执行指令的时候,可以直接从指令码中取出地址,而不必经过计算或其他操作,所以叫做直接寻址。

4.  寄存器间接寻址

采用寄存器间接(Indirect)寻址方式的操作数的地址放在寄存器中。 

    MOV ESI,00404011H
    
MOV EAX,[ESI]

注意,MOV EAX,ESI和MOV EAX,[ESI]的区别。 

在8086/8088/80286等16位的CPU中,只有4个寄存器能用做寄存器间接寻址:BX,BP,SI,DI。因此,寄存器间接寻址智能是下列之一: [BX],[BP],[SI],[DI]。而在80386及以后的32位CPU中,下面8个寄存器能用做寄存器间接寻址:EAX,EBX,ECX,EDX,ESI,EDI,EBP,ESP。

5. 寄存器相对寻址 

寄存器相对寻址方式的操作数,其地址是寄存器和一个立即数相加后得到的结果。寄存器的内容不直接作为操作数的地址,寄存器的内容再加上一个“相对量”(displacement)后,就得到内存的地址。  

    MOV ESI,0040200AH
    
MOV EDI,[ESI+4]

相对量也可以是一个负数:

    MOV EDI,[ESI-4]


6.基址变址寻址

基址变址寻址方式的操作数,其地址是两个寄存器相加后得到的结果。这里的两个寄存器分别称为基址寄存器(Base Register)和变址寄存器(Index Register)。 

    MOV ESI,0040200AH
    
MOV EBX,4
    
MOV EDI,[EBX+ESI]

在8086/8088/80286等16位的CPU中,基址寄存器有两个:BX和BP,变址寄存器也有两个:SI和DI。因此,基址变址寄存器只能是4种组合之一:[BX+SI],[BX+DI],[BP+SI]和[BP+DI]。而在80386及以后的32位CPU中,基址寄存器有8个:EAX,EBX,ECX,EDX,ESI,EDI,EBP和ESP,变址寄存器有7个:EAX,EBX,ECX,EDX,ESI,EDI和EBP。ESP只能作为基址寄存器,而不能作为变址寄存器。 

7. 相对基址加变址寻址

基址变址相对寻址方式的操作数,其地址是两个寄存器以及一个立即数相加后得到的结果。“基址变址相对”的3个元素代表:基址寄存器(base register)、变址寄存器(index register)和相对量(displacement)。 

     MOV ESI,0040200AH
     
MOV EBX,4
     
MOV EDI,[EBX+ESI+4]

相对量为0的基址变址相对寻址就是基址变址寻址。 


8. 基址变址比例相对寻址

基址变址比例相对寻址方式的操作数,其地址是由基址寄存器、变址寄存器乘以一个比例数和相对量这3个部分相加得到的结果。比例数只能有1,2,4,8。    

     ;地址 = 基址寄存器 + 变址寄存器 * [1 | 2 | 4 | 8] + 相对量
     MOV ESI,0040200AH
     
MOV EBX,4
     
MOV EDI,[ESI+EBX*2+4

* 内存操作数的地址又称为有效地址(EA Effective Address)。立即寻址和寄存器寻址中,操作数是立即数和寄存器,没有有效地址。 

9. 直接端口寻址

直接端口寻址是在指令中直接给出要访问的端口地址,一般采用2位十六进制数表示,也可以是符号,访问的端口范围0~255. 

  IN AL,20H

表示从I/0端口地址为20H的端口中取数据送入AL寄存器中。

10. 间接端口寻址

若访问的端口地址大于255时,就要用间接寻址方式。可以访问的端口范围0~65535.   

  MOV DX,356H   ;将端口地址356H送入DX寄存器
  OUT DX,AL       ;将AL中的内容输出到DX指定的端口 

寻址方式小结: 

内存操作数的地址又称为有效地址(EA Effective Address)。立即寻址和寄存器寻址中,操作数是立即数和寄存器,没有有效地址。 

|------------------|-----------------------------|--------------------|
| 寻址方式          |  操作数地址计算方式           |                 |
|------------------|-----------------------------|--------------------|
| 立即寻址          |  不需要                       |  0FFFFFFFFH        |
|------------------|-----------------------------|--------------------|
| 寄存器寻址         |  不需要                      |  EAX               |
|------------------|-----------------------------|--------------------|
| 直接寻址          |  直接在指令中取出               |  [004020FCH]       |
|------------------|-----------------------------|--------------------|
| 寄存器间接寻址      |  EA=寄存器                   |  [EAX]             |
|------------------|-----------------------------|--------------------|
| 寄存器相对寻址      |  EA=寄存器+相对量             |  [EAX+
4]           |
|------------------|-----------------------------|--------------------|
| 基址变址寻址       |  EA=寄存器+寄存器             |  [EAX+EBX]         |
|------------------|-----------------------------|--------------------|
| 基址变址相对寻址    |  EA=寄存器+寄存器+相对量       |  [EAX+EBX-
8]       |
|------------------|-----------------------------|--------------------|
| 基址变址比例相对寻址 |  EA=寄存器+寄存器*比例+相对量   |  [EAX+EBX*
8+20]    |
|------------------|-----------------------------|--------------------|

段超越:

内存操作数的地址由两个部分指定:段和有效地址。寻址方式中确定操作数的有效地址后,还要依靠段寄存器一起来确定操作数的内存地址。

在没有指定段寄存器的情况下,如果在寻址方式的有效地址中使用了ESP和EBP寄存器,那么使用SS段寄存器。对所有其他情况,使用DS段寄存器。

例如,下面指令中的内存操作数在SS段中: 

     MOV EAX,[EBP+8]
     
MOV EBX,[ESP-4]

例如,下面指令中的内存操作数在DS段中: 

     MOV EAX,[EBX+8]
     
MOV EBX,[ESI-4]
     
MOV EAX,[0040200AH]

使用段超越前缀可以改变在寻址方式中默认使用的段寄存器,明确地指定操作数位于哪一个段中。 

     MOV EAX,CS:[EDI]
     
MOV EBX,ES:[ESP-4]
     
MOV DS:[EBP],ECX

CS段寄存器只能用来读取数据,因此,只能作为源操作数的段前缀。

在Windows 32位环境中,FS段中保存的是系统使用的一些信息,如果要访问这个段的内存时,必须明确指出段寄存器为FS。

在Windows 32位环境中,CS,DS,ES,SS在内存中指向同一个段,其大小为4GB。所以,程序中一般不需要使用段超越前缀来指定操作数的段寄存器。 

原文地址:https://www.cnblogs.com/mumuliang/p/1885064.html