汇编语言内存模式指令简述

如果 Mod R/M 字节只用于标识寄存器操作数,那么 Intel 指令编码就会相对简单。实际上,Intel 汇编语言有着各种各样的内存寻址模式,这就使得 Mod R/M 字节编码相当复杂。(指令集的复杂性是 RISC 设计支持者常见的批评理由。)

Mod R/M 字节正好可以指定 256 个不同组合的操作数。下表列岀了 Mod 00 时的 Mod R/M 字节(十六进制)。

字节 AL CL DL BL AH CH DH BH  
AX CX DX BX SP BP SI DI
寄存器ID 000 001 010 011 100 101 110 111
Mod R/M Mod R/M 值 有效地址
00 000 00 08 10 18 20 28 30 38 [BX+SI]
  001 01 09 11 19 21 29 31 39 [BX+DI]
  010 02 0A 12 1A 22 2A 32 3A [BP+SI]
  011 03 0B 13 1B 23 2B 33 3B [BP+DI]
  100 04 0C 14 1C 24 2C 34 3C [SI]
  101 05 0D 15 1D 25 2D 35 3D [DI]
  110 06 0E 16 1E 26 2E 36 3E 16 位偏移量
  111 07 0F 17 1F 27 2F 37 3F [BX]

Mod R/M 字节编码的作用如下:Mod 列中的两位指定寻址模式的集合。比如,Mod 00 有 8 种可能的 R/M 数值(000b〜111b),有效地址列给岀了这些数值标识的操作数类型。

假设想要编码 MOV AX, [Si], Mod 位为 00b, R/M 位为 100b。从《x86指令编码》一节中的 16 位 RM 表中可知 AX 的寄存器编号为 000b,因此完整的 Mod R/M 字节为 00 000 100b 或 04h:

mod reg r/m
00 000 100

十六进制字节 04 在上表(Mod R/M)的 AX 列第 5 行。

MOV [SI], AL 的 Mod R/M 字节还是一样的(04h),因为寄存器 AL 的编号也是 000。现在对指令 MOV [SI], AL 进行编码。8 位寄存器的传送操作码为 88。Mod R/M 字节为 04h,则机器码为 88 04。

MOV 指令示例

下表列出了 8 位和 16 位 MOV 指令所有的指令格式和操作码。

操作码 指令 说明 操作码 指令 说明
88/r MOV eb, rb 字节寄存器送 EA 字节操作数 8E/2 MOV SS, rw 字寄存器送 SS
89/r MOV ew, rw 字寄存器送 EA 字操作数 8E/3 MOV DS, mw 内存字送 DS
8A/r MOV rb, eb EA 字节操作数送字节寄存器 8E/3 MOV DS, rw 字寄存器送 DS
8B/r MOV rw, ew EA 字操作数送字寄存器 A0 dw MOV AL, xb 字节变量(偏移量为 dw)送 AL
8C/0 MOV ew, ES ES 送 EA 字操作数 A1 dw MOV AX, xw 字变量(偏移量为 dw)送 AX
8C/1 MOV ew, CS CS 送 EA 字操作数 A2 dw MOV xb, AL AL 送字节变量(偏移量为 dw)
8C/2 MOV ew, SS SS 送 EA 字操作数 A3 dw MOV xw, AX AX 送字寄存器(偏移量为 dw)
8C/3 MOV ew, DS DS 送 EA 字操作数 B0+rb db MOV rb, db 字节立即数送字节寄存器
8E/0 MOV ES, mw 内存字送 ES B8+rw dw MOV rw, dw 字立即数送字寄存器
8E/0 MOV ES, rw 字寄存器送 ES C6 /0 db MOV eb, db 字节立即数送 EA 字节操作数
8E/2 MOV SS, mw 内存字送 SS C7 /0 dw MOV ew, dw 字立即数送 EA 字操作数

下面两表给出了上表中缩写符号的补充信息。手动汇编 MOV 指令时可以用这些表作为参考。

/n: 操作码后面跟一个 Mod R/M 字节,该字节后面可能再跟立即数和偏移量字段。数字 n( 0〜7 )为 Mod R/ M 字节中 reg 字段的值
/r: 操作码后面跟一个 Mod R/M 字节,该字节后面可能再跟立即数和偏移量字段
db: 操作码和 Mod R/M 字节后面跟一个字节立即操作数
dw: 操作码和 Mod R/M 字节后面跟一个字立即操作数
+rb: 8 位寄存器的编号(0〜7 ),与前面的十六进制字节一起构成 8 位操作码
+rw: 16 位寄存器的编号(0〜7 ),与前面的十六进制字节一起构成 8 位操作码

db -128〜+127 之间的有符号数。若操作数为字类型,则该数值进行符号扩展
dw 指令操作数为字类型的立即数
eb 字节类型操作数,可以是寄存器也可以是内存操作数
ew 字类型操作数,可以是寄存器也可以是内存操作数
rb 用数值(0〜7 )标识的 8 位寄存器
rw 用数值(0〜7 )标识的 16 位寄存器
xb 无基址或变址寄存器的简单字节内存变量
xw 无基址或变址寄存器的简单字内存变量

下表列出了更多的 MOV 指令,这些指令能手动汇编,且可以与表中的机器代码比较。假设 myWord 的起始地址偏移量为 0102h。

指令 机器码 寻址模式
mov ax, my Word A1 02 01 直接(为 AX 优化)
mov my Word,bx 89 IE 02 01 直接
mov[di],bx 89 ID 变址
mov[bx+2],ax 89 47 02 基址 - 偏移量
mov[bx+si],ax 89 00 基址 - 变址
mov word prt [bx+di+2], 1234h C7 41 02 34 12 基址 - 变址 - 偏移量

爱面试的程序媛,一个分享面试经验的公众号。跟着站长一起学习,每天都有进步。

通俗易懂,深入浅出,定时分享程序员面试的那点事。

面试如何造火箭?工作如何拧螺丝?都在这个公号哦。

扫描二维码关注公众号,免费领取价值 1000 元的求职面试资料(限时免费)!

当你决定关注「爱面试的程序媛」,你已然超越了90%的程序员!

爱面试的程序媛二维码
微信扫描二维码关注