计算机系统基础 4 寻址方式

        对于一条指令,我们重点关注它两点:执行什么样的操作,操作数在哪里。

        操作数存放的位置即为存放地址,一般是CPU内寄存器、主存、或者I/O设备端口。当操作数在主存时,我们重点关注段址/段选择符、段内偏移。

        寻找操作数存放地址的方式称为寻址方式。

        双操作数的指令格式为:操作符  OPD OPS,如ADD  EAX  EBX,执行(OPD) +  (OPS)   ➡   OPD( (EAX) (目的操作数地址) + (EBX)(源操作数地址)   ➡   EAX)

立即寻址 

        操作数直接放在指令中,在指令的操作码后;

        操作数是指令的一部分,位于代码段中;

        指令中的操作数是8位、16位或32位二进制数。

        立即操作数只能为源操作数。

        使用格式:

         例如: MOV  EAX , 12H     机器码:     B8 12 00 00 00

int   global;   // 注:global 是全局变量	
global = 2 * 5 ;

/*


00521A17      C7 05 B8 A5 52 00 0A 00 00 00 
              mov  dword ptr [global (052A5B8h)], 0Ah 


*/

寄存器寻址 

        使用格式: R

        功    能: 寄存器R中的内容即为操作数。

        说    明: 除个别指令外,R可为任意寄存器。

        例如:DEC   BL

  •         执行前 :  (BL) = 43H
  •         执    行:   (BL) – 1 = 43 H –1 = 42H ➡  BL
  •         执行后:   (BL) = 42H

直接寻址 

        操作数在内存中;

        操作数的偏移地址EA紧跟在指令操作码后面。

int global;
void address_compare()
{
   int local;
   global = 2*5;
   *((char *)&global + 1) = 20;
   printf("global = %d  %08x\n", global, global);

   local = 10;
   *((char*)&local + 1) = 20;
   printf("local = %d  %08x\n", local, local);
}

        全局变量的访问——直接寻址

         局部变量的访问——变址寻址(见后)

寄存器间接寻址 

        格式:[R]

        功能:操作数在内存中,操作数的偏移地址在寄存器R中。即(R) 为操作数的偏移地址。

        例如:MOV  AX, [ESI] 

        R 可以是:832位通用寄存器中的任意一个

        操作数的偏移地址:在指令指明的寄存器中

        操作数所在的段:   扁平内存管理模式下,(DS=SS

变址寻址 

        格式:V [ R × F ]

        功能:R中的内容 × F + V  为操作数的偏移地址

        例如:MOV  AL, 5[EBX*2]

        R 可以是832位通用寄存器,F 可为 1248

 

  • 全局变量编译后对应一个数值化的地址
  • 局部变量编译后对应一个地址为 [ebp – n]

基址加变址寻址 

格式: [BR+IR × F + V]

       或 V[BR][IR×F]  或  V [IR×F][BR]  或  V[BR+IR×F]

功 能:操作数的偏移 = 变址寄存器IR中的内容 × 比例因子F + 位移量V + 基址寄存器BR中的内容 。

EA = (IR)*F + V + (BR)

 例如:MOV  EAX, -6[EDI*2][EBP]

F 可为 1,2,4,8;
当使用32位寄存器时:

   BR可以是 EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP 之一;

   IR 可以是除ESP外的任一32位寄存器;

   未带比例因子的寄存器是 BR;

   当没有比例因子时,写在前面的寄存器是BR。

操作数的类型:

   若V为变量,则操作数类型为变量的类型;

   若V为常量,类型未知。

    当 V 中存在全局变量或标号时,用的段都是 DS,在 VS2019中, (DS)=(SS)。CS中的全局变量等同 DS段中的变量。

x86机器指令编码规则

① 指令前缀(prefix,非必需,0个或多个字节)

② 操作码(opcode,必须,1字节 ~ 3字节)

③ 内存/寄存器操作数(ModR/M,非必需): 指明寻址方式

④ 索引寻址描述 (SIB,非必需):指明基址寄存器、变址寄存器、比例因子

⑤ 地址偏移量(Displacement,非必需)

⑥ 立即数(Immediate,非必需)

操作码:

  • 指明了要进行操作。
  • 指明操作数的类型(一般看最后一个二进制)0:字节操作;  1字操作(32位指令中为双字操作);有指令前缀 66H对字操作。
  • 指明源操作数是寄存器寻址,还是目的操作数是寄存器寻址 (操作码的倒数第二个二进制位1目的操作数是寄存器寻址,0源操作数寄存器寻址;[寻址方式字节]配合使用

内存/寄存器操作数(ModR/M) :

Mod由2个二进制位组成,取值是00、01、10、11。
Mod与为R/M配合使用,明确一个操作的获取方法。
Reg/Opcode 确定另外一个寄存器寻址的寄存器编码
  • Mod=00, R/M =000,表示 用 [EAX] 寻址
  • Mod=00,R/M=100,  表示用[--][--] ,无位移量的基址加变址,在 SIB 字节指明基址/变址寄存器的编码

        Reg/Opcode 的编码:同一编码有多个寄存器,用哪一个寄存器,取决于指令前缀和操作码中的编码

mov  eax, [ebx]    ; 机器码是:8B 03    ➡ 00  000  011     [EBX]

mov [ebx], eax     ; 机器码是:89 03    ➡ 1000 1001  VS 1000 1011

操作码的倒数第二位:   1OPD是寄存器, 0OPS是寄存器

相关推荐

  1. 【汇编】指令系统方式

    2024-03-25 21:06:07       15 阅读
  2. arm方式

    2024-03-25 21:06:07       36 阅读
  3. 常见的数据方式

    2024-03-25 21:06:07       7 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-25 21:06:07       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-25 21:06:07       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-25 21:06:07       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-25 21:06:07       18 阅读

热门阅读

  1. typeScript3(数组类型)

    2024-03-25 21:06:07       18 阅读
  2. 【58. 最后一个单词的长度】

    2024-03-25 21:06:07       21 阅读
  3. 面对数据集不平衡的分类任务怎么办?

    2024-03-25 21:06:07       16 阅读
  4. 《c++》继承同名静态成员处理方式

    2024-03-25 21:06:07       19 阅读
  5. 【Leetcode】代码随想录Day15|二叉树2.0

    2024-03-25 21:06:07       18 阅读
  6. 毕业论文的问题猜想及答案整理

    2024-03-25 21:06:07       18 阅读
  7. Python学习笔记01

    2024-03-25 21:06:07       18 阅读
  8. 碎碎念-记一下LSPatch的原理

    2024-03-25 21:06:07       17 阅读
  9. 【笔试】美团2024年春招第二场笔试(技术)

    2024-03-25 21:06:07       21 阅读
  10. Linux的目录结构和文件管理命令

    2024-03-25 21:06:07       17 阅读