手机版 | 登陆 | 注册 | 留言 | 设首页 | 加收藏
当前位置: 网站首页 > 软件工程 > 汇编语言 > 文章 当前位置: 汇编语言 > 文章

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

时间:2023-12-22    点击: 次    来源:网络    作者:佚名 - 小 + 大

https://www.coder.work/article/8115373

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

我正在编写一个 8086 汇编器,它接受指令并生成 8086 机器代码。我使用《Intel 8086 用户手册》作为引用。

为了说清楚,我将解释一下情况。假设我想汇编这条指令 mov ax, bx。我查了一下手册,发现当mov的操作数是2个16bit寄存器时,mov的操作码是0x89,并指定操作数(源和目标),在本例中 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

我假设每条指令的位移长度分别为8位、8位、16位,这是否错误?

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

问题是,为什么第二条指令中的MOD字段是10b或0x02而不是01b或0x01?应该是0x01,因为位移是8位位移,不是吗?为什么第三条指令中的MOD是0x01,尽管位移是16位?为什么汇编器忽略其余的位移并仅捕获 1 个字节?

最佳答案

位移的大小取决于“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,您必须在 clc 之前插入额外的 nop 指令作为填充,以确保指令对齐2 字节边界(由 align 2 指令请求),而对于较大的(4 字节)mov 则不需要(因此少了 1 条指令,但结果代码的字节数相同)。

关于assembly - 位移值对 ModRegRm 字节的 Mod 字段有什么影响?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61707459/

上一篇:二种常用的汇编语言编程环境

下一篇:程序段前缀

备案ICP编号  |   QQ:285250603  |  地址:湛江市  |  电话:15322199012  |  
Copyright © 2026 天人文章管理系统 版权所有,授权www.yajiupc.top使用 Powered by 55TR.COM