移位值对ModRegRm字节的Mod字段有什么影响?

问题描述 投票:0回答:1

我正在编写一个8086汇编器,接受指令并产生8086机器代码。我以《英特尔8086用户手册》为参考。

为了说清楚,我将解释一下情况。比如说我想组装这个指令。mov ax, bx. 我查了一下手册,发现当操作数为 mov 是2个16位寄存器,操作码为 mov0x89 并指定操作数(源和目的地)。mov在这种情况下,后面跟着一个ModRegRm字节,指定源和目标,在这种情况下,它是 0xd8. 这个二进制的字节= 11011000.

Mod为2位,Reg、Rm各为3位.所以,Mod=11,Reg=011,Rm=000.这里很简单,但有一点我不明白,就是寻址模式和位移。

modregrm-table

看表和下面的三个指令及其机器代码。

mov [bx+0x6], ax ;894706

mov [bx+0xbf],ax ;8987BF00

mov [bx+0xffff],ax ;8947FF

我认为每条指令中的位移长度分别是8bit,8bit,16bit,我说的对吗?

我认为我是对的,因为很明显。0x60xbf 是1个字节和 0xffff 是两个字节。

问题是,为什么第二条指令中的MOD字段是 10b or 0x02 而不是 01b or 0x01? 应该是 0x01 因为位移是8bit的位移,不是吗?而为什么MOD是 0x01 为什么在第三条指令中,即使位移是16bit,汇编器也忽略了其余的位移,只捕获了1个字节?

assembly x86-16 machine-code addressing-mode sign-extension
1个回答
4
投票

移位的大小取决于 "MOD "字段(如MOD=001b则为8位,MOD=010b则为16位),并按预定大小进行符号扩展。

这意味着像这样的指令 mov [bx+6], ax 可以编码为 mov [bx+0x0006], ax (MOD=010b,位移量为16位),也可以编码为 mov [bx+0x06], ax (用MOD=001b,位移8位)。

以同样的方式。mov [bx+65535],ax 可以用任何一种方式编码(8位位移或16位位移);因为0xFF可以符号扩展到0xFFFF。

但是。mov [bx+191],ax 不能用8位位移编码,因为当191(0xBF)被符号扩展后,就变成了0xFFBF,这不等于191。它必须使用16位的位移。

本质上;如果全16位位移的最高9位都是相同的(对于值0x0000到0x007F全部清零,或者对于值0xFF80到0xFFFF全部设置),它可以编码为8位位移或16位位移;否则必须使用16位位移。

当要在不同的编码之间进行选择时;一个好的汇编器会选择最小的可能性(并使用8位位移,因为它使指令缩短了1个字节)。如果避免了填充的需要(如果后面的指令需要在某个边界上对齐),一个更优秀的汇编器可能会使用更大的版本。举个例子 .align 2 然后 mov [bx+6], ax 然后 .align 2 然后 clc - 与较小的(3字节) mov 你必须插入一个额外的 nop 指令前的填充物。clc 以确保指令在2字节边界上对齐(由 align 2 指令),并使用较大的(4字节) mov 你不需要(所以少了1条指令,但结果代码的字节数是一样的)。

© www.soinside.com 2019 - 2024. All rights reserved.