关于x86的寻址方式

来源:互联网 发布:国外毕业证翻译 淘宝 编辑:程序博客网 时间:2024/05/16 19:17

一. 概述

x86 汇编程序都是分段程序设计结构,每个程序段都有一个开始地址:段基址。

在保护模式下段基址要由16位的段选择子得到,这些段选择子存放在六个段寄存器(CS,SS,DS,ES,FS,GS)中:

段选择子一直都只有16位,它表示的是段描述符表中内容的下标,目前16 位已经够用了,其它的原因也就不可而知了。

代码段CS 段寄存器来指示;

堆栈段SS 段寄存器来指示;

附加数据段 ES 段寄存器作为目标操作数的段寄存器;

   一般的数据段可用 DS、ES、FS、GS来指示,但 DS 作为数据段的默认段寄存器,用它来寻址比其它几个段寄存器的效率高,因此最好安排 DS 寻址最常引用的数据段,而 ES、FS、GS去寻址一些不常用的数据段。

    

基址、变址、位移量的值可正可负,比例因子只能为正。

    1:基址
    (32位寻址):
        1):如果基址寄存器是  ESP或EBP,则段寄存器为 SS;
        2):如果基址寄存器是其它通用寄存器,则段寄存器为 DS;
    (16位寻址):
        基址寄存器可以是  BX  或  BP

    2:变址
    (32位寻址):
        变址寄存器可以为除  ESP  之外的32位通用寄存器
    (16位寻址):
        变址寄存器可以是  SI  或  DI
    3:比例因子
        一个常数,可取  1、2、4、8。
    4:位移量
        一个8位、16位、32位的常数。

二:详解
    默认情况下,存储器寻址使用DS数据段,可以使用段寄存器来显式指出选择的段。


    1:立即寻址
       对多字节立即数,高字节放在寄存器高位,低字节放在寄存器低位。
       例:
           MOV  BL,43                ;把十进制数43放入BL中
           MOV  AX,98H             ;把十六进制数98H放入AX中
           MOV  AL,'A'                 ;把字符'A'的ASCII码放入AL中
           MOV  CX,'AB'             ;把字符'AB'的ASCII码放入CX中

    2:寄存器寻址
       指令中必须是同长的寄存器

    3:直接寻址
       指令中直接提供源操作数的偏移地址,它作为代码的一部分存放在代码段中。
       例:
           MOV  BL,DS:[00300H]              ;把DS数据段中偏移地址为300H的字节复制到BL
           MOV  CX,ES:[00300H]              ;把ES数据段中偏移地址为300H的字复制到CX
           MOV  EAX,DwordVar                 ;把DS数据段中DwordVar单元复制到EAX
           MOV  CL,ByteVar                       ;把DS数据段中ByteVar单元复制到CL


    4: 寄存器间接寻址
       操作数的有效地址存放在指令指明的寄存器中,能够用作间接寻址的寄存器有:
       EAX,EBX,ECX,EDX,ESI,EDI --> 使用  DS  作为段寄存器
       ESP,EBP                 --> 使用  SS  作为段寄存器
       例:
           LEA  EBX, ARRAY                  ;把数组开始地址送EBX
           MOV  AL, [EBX]                   ;访问数组的第0个元素,若要访问其它元素,只需增加数组索引EBX的值

           MOV  AX, [EBP]                    ;把SS段中EBP指向的字单元复制到 AX
           MOV  [EBP], AX                    ;把AX的值复制到SS段中EBP指向的单元
           MOV  [EDI], AL                     ;把AL的值复制到DS段中EDI指向的单元
           MOV  AL, [EDX]                    ;把DS段中EDX指向的字节单元复制到 AL

    5:寄存器相对寻址
       有效地址EA等于寄存器R中的内容与位移量X的和,即  EA  =  X  +  [R],该方式适用于数组、表格处理。
       EAX,EBX,ECX,EDX,ESI,EDI     -->    使用  DS  作为段寄存器
       ESP,EBP                                     -->    使用  SS  作为段寄存器
       例:
           MOV  AX, Table[ESI]                ;Table中存放表的首地址,ESI存放要访问的表项的索引
           MOV  AX, [Table + ESI]            ;(MOV  AX, [Table + ESI])  == (MOV  AX, Table[ESI])


           MOV  AX, 100H[ESI]                      ;把DS段中ESI加100H的字存储单元的内容复制到 AX
           MOV  ARRAY[EDI], AL                   ;把AL的值复制到DS段中ARRAY中的第EDI字节单元中
           MOV  LIST[EDI+3], AX                 ;把AX的值复制到DS段中EDI+LIST+3的字单元中
           MOV  ARRAY[EBX],EAX                ;把EAX的值复制到DS段中ARRAY+EBX的双字单元中

    6:基址变址寻址 
       ESP不能作为变址寄存器。汇编器按如下规则区分基址寄存器和变址寄存器:指令的第二操作数中的第一个寄存器为基址寄存器,第二

个寄存器为变址寄存器。比如 MOV  EAX, [EDX][ESI](或MOV  EAX, [EDX+ESI])中,EDX  为基址寄存器,ESI  为变址寄存器。该方式适用

于数组、表格的处理。
       例:
           MOV  AX, [EBX+ESI]                 ;DS段中地址为EBX+ESI的存储单元的字数据送AX
           MOV  AX, [EBP+ESI]                 ;SS段中地址为EBP+ESI的存储单元的字数据送AX
           MOV  AX, ES:[EBX+ESI]           ;ES段中地址为EBX+ESI的存储单元的字数据送AX

    7:相对基址变址寻址
       该方式适用于二维数组的寻址。
       EA  =  X  +  [BP]  +  [IR]
       例:
           MOV  AX,  Disp[EBX][EDI] 或
           MOV  AX,  Disp[EBX+EDI] 或
           MOV  AX,  [Disp+EBX+EDI]

    以下三种方式中,任何32位通用寄存器都能用作基址寄存器,除ESP之外的32位通用寄存器均可作为变址寄存器;
    若比例因子为1,指令的第二操作数中的第一个寄存器为基址寄存器,第二个寄存器为变址寄存器。若基址寄存器为EBP或ESP,则默认的段
寄存器是SS;若基址寄存是其它的寄存器,则默认的段寄存器是DS。
    若比例因子为2、4、8,则与比例因子相乘的那个寄存器是变址寄存器。

    8:比例变址寻址方式
       EA  =  X  +  [IR  *  K]
       和寄存器相对寻址相比增加了比例因子,优点在于:对元素大小为2、4、8字节的数组,可在变址寄存器中给出数组元素的下标。
       例:
           MOV  EAX,  ARRAY[ESI*4]           ;将ARRAY数组中第  (ESI)  个元素送EAX,其中ARRAY数组中元素大小为4

    9:基址比例变址寻址
       EA  =  [BR]  +  [IR  *  K]
       例:
           LEA  EBP, ARRAY                         ;把数组开始地址送EBX
           MOV  EAX,  [EBP][ESI*4]           ;将ARRAY数组中第  (ESI)  个元素送EAX,其中ARRAY数组中元素大小为4

    10:相对基址比例变址寻址
       EA  =  X  +  [BR]  +  [IR  *  K]
       例:
           MOV  AL,  0040400H[EBX][ESI*2]          

           MOV  [EAX+EDI*2+15H],  DX              ;  把DX寄存器的内容复制到数据段的一存储单元,
                                                                                  ;  该存储单元EA = EAX+EDI*2+15H

           MOV  AL, [EBP+ESI*2-30H]                     ;  把堆栈中的一字节单元的内容复制到AL中,
                                                                                  ;  该存储单元EA = EBP+ESI*2-30H

0 0