汇编语言处理器操作数大小前缀作用及意义


现在将注意力转回到 x86 处理器(IA-32)的指令编码。有些指令以操作数大小前缀开始,覆盖了其修改指令的默认段属性。问题是,为什么有指令前缀?在编写 8088/8086 指令集时,几乎所有 256 个可能的操作码都用于处理带有 8 位和 16 位操作数的指令。

当 Intel 开发 32 位处理器时,就需要想办法发明新的操作码来处理 32 位操作数,而同时还要保持与之前处理器的兼容性。对于面向 16 位处理器的程序,所有使用 32 位操作数的指令都添加一个前缀字节。

对于面向 32 位处理器的程序,默认为 32 位操作数,因此所有使用 16 位操作数的指令添加一个前缀字节。8 位操作数不需要前缀。

【示例】16 位操作数,现在对 MOV 指令进行汇编,以此为例来看看在 16 位模式下前缀字节是如何起作用的。.286 伪指令指明编译代码的目标处理器,确保不使用 32 位寄存器。下面的每条 MOV 指令都给岀了其指令编码:
.model small
.286
.stack 100h
.code
main PROC
    mov ax, dx    ; 8B C2
    mov al, dl    ; 8A C2
现在对 32 位处理器汇编相同的指令,使用 .386 伪指令,默认操作数为 32 位。指令将包括 16 位和 32 位操作数。第一条 MOV 指令(EAX、EDX)使用的是 32 位操作数,因此不需要前缀。第二条 MOV(AX、DX)指令由于使用的是 16 位操作数,因此需要操作数大小前缀(66):
.model small
.386
.stack 100h
.code
main PROC
    mov    eax,edx ; 8B C2
    mov    ax,dx   ; 66 8B C2
    mov    al,dl   ; 8A C2