x86 操作码编码中的方向/符号扩展位
在 x86 指令集中,操作码索引 1 处的位可以是指定目标操作数和源操作数的方向位,也可以是符号扩展位。
例如 add
00 /r ADD r/m8 , r8
与02 /r ADD r8, r/m8
对于相同的助记符81 /0 id ADD r/m32, imm32
, 该位区分r/m, reg
与reg, r/m
与83 /0 ib ADD r/m32, imm8
完整(位 1 清除)与符号扩展立即数(位 1 设置)
我想知道确定这属于哪种情况的最简单的逻辑方法是什么。除了检查指令操作码并比较它们以找出它是什么(对于指令的符号扩展或方向位变体)之外,还有其他方法可以检查吗?还有一些指令忽略该位,但由于它被设置为 0,所以它并不重要。
编辑:事实证明,对于写错误(这就是我的代码的目的), reg->r/m 始终是这种情况,因为 ar/m->reg 指令永远不会触发写错误。但如果其他人遇到类似的问题,任何信息仍然会很好。
In the x86 instruction set the the bit at index 1 of an opcode can either be the direction bit which specifies what the destination and source operands are or it can be a sign extend bit.
e.g. for add
00 /r ADD r/m8, r8
versus02 /r ADD r8, r/m8
That bit distinguishesr/m, reg
vs.reg, r/m
for the same mnemonic81 /0 id ADD r/m32, imm32
versus83 /0 ib ADD r/m32, imm8
full (bit 1 cleared) vs. sign-extended immediate (bit 1 set)
I'm wondering what's the easiest logical way to determine which of these cases it is. Is there a way to check other than checking the instruction opcodes and comparing them to find out which it is (for the sign extend or direction bit variants of the instructions)? There are also instructions that disregard this bit but since it's set to 0 then it doesn't really matter.
EDIT: Turns out that for write faults (which is what my code was intended for), reg->r/m is always the case because a r/m->reg instruction will never trigger a write fault. But any information would still be nice in case someone else is running into a similar issue.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
方向和符号位是 x86 处理器标志寄存器的一部分。由于标志的最低八位与 8080/8085/Z80 的标志具有相同的布局,我的猜测是索引 1 处的位是有符号位。如果我没记错的话,自 70 年代末 8086/88 处理器引入方向位以来,方向位的位置一直没有改变。
符号位位作为算术运算的结果而被修改,并且是运算结果的最高位的副本。 INC 和DEC 不影响符号位。
方向位使用 cld/std 指令进行操作,并控制块指令(cmps、ins、lods、movs、outs、scas 和 stos)是否后递增/递减。
它们也可以通过堆栈进行操作(尽管这对于符号位可能没有意义)
使用“and”是一个示例:也可以使用 or、xor 等。
如果您操作该标志,您可能必须将其恢复到以前的值,因为某些运行时库假设它没有被修改。
The direction and sign bits are part of the flags register of the x86 processors. Since the lowest eight bits of the flags have the same layout as the flags of the 8080/8085/Z80 my guess is that the bit at index 1 is the signed bit. The position of the direction bit has not changed since it was introduced with the 8086/88 processors in the late 70s if my memory serves me.
The sign bit bit is modified as a result of an arithmetic operation and is a copy of the highest bit of the operation's result. INC and and DEC do not affect the sign bit.
The direction bit is manipulated using the cld/std instruction and controls whether the block instructions (cmps, ins, lods, movs, outs, scas and stos) post-increment/-decrement.
They may also be manipulated via the stack (though this is perhaps not meaningful with the sign bit)
Using "and" is an example: or, xor and others may also be used.
If you manipulate the flag you may have to restore it to its previous value as some run-time libraries assume that it isn't modified.
[评论已成为答案]。
显然,您需要一个针对指令字节流的布尔公式。我不知道如何轻松定义该公式; x86 的指令集非常混乱。我希望关键技巧是在由前缀字节确定的表中查找操作码字节。如果您正在编写某种反汇编程序,我希望您已经拥有这样的表。
[Comment made into answer].
You obviously need a boolean formula over the stream of instruction bytes. I wouldn't know how to define that formula easily; the x86 has a really messy instruction set. I'd expect the key trick is to lookup the opcode byte in a table determined by the prefix bytes. If you are writing some kind of disassembler, I'd expect you to have such tables already anyway.