6

在 x86 指令集中,操作码索引 1 处的位可以是指定目标和源操作数的方向位,也可以是符号扩展位。

例如对于add

  • 00 /r ADD r/m8, r802 /r ADD r8, r/m8
    该位区分r/m, regreg, r/m相同的助记符
  • 81 /0 id ADD r/m32, imm3283 /0 ib ADD r/m32, imm8
    完整(第 1 位清零)与符号扩展立即数(第 1 位设置)

我想知道确定其中哪种情况的最简单的逻辑方法是什么。除了检查指令操作码并比较它们以找出它是什么(对于指令的符号扩展或方向位变体)之外,还有其他方法可以检查吗?还有一些指令忽略该位,但由于它设置为 0,所以它并不重要。

编辑:事实证明,对于写错误(这是我的代码的目的), reg->r/m 总是如此,因为 ar/m->reg 指令永远不会触发写错误。但是,如果其他人遇到类似问题,任何信息仍然会很好。

4

2 回答 2

4

[评论成为答案]。

您显然需要对指令字节流使用布尔公式。我不知道如何轻松定义该公式;x86 的指令集非常混乱。我希望关键技巧是在由​​前缀字节确定的表中查找操作码字节。如果您正在编写某种反汇编程序,我希望您已经拥有这样的表。

于 2011-08-03T07:26:24.970 回答
1

方向和符号位是 x86 处理器标志寄存器的一部分。由于标志的最低八位与 8080/8085/Z80 的标志具有相同的布局,我猜测索引 1 处的位是有符号位。如果我没记错的话,自从 70 年代后期在 8086/88 处理器中引入以来,方向位的位置一直没有改变。

符号位位作为算术运算的结果被修改,并且是运算结果的最高位的副本。INC 和 DEC 不影响符号位。

方向位使用 cld/std 指令进行操作,并控制块指令(cmps、ins、lods、movs、outs、scas 和 stos)是否后增/减。

它们也可以通过堆栈进行操作(尽管这可能对符号位没有意义)

pushf
and dword ptr [esp],SOME_MASK
popf

使用“and”就是一个例子:or、xor 等也可以使用。

如果您操纵该标志,则可能必须将其恢复为以前的值,因为某些运行时库假定它没有被修改。

于 2011-08-04T14:41:02.850 回答