【问题标题】:x86 sub instruction opcode confusion [duplicate]x86子指令操作码混淆[重复]
【发布时间】:2021-10-23 05:00:55
【问题描述】:

玩了一下 Turbo Assembler 和 Turbo Debugger,我对操作码感到惊讶。更准确地说,我有一些组装好的二进制文件,Turbo Debugger 在其中反汇编这个词

29 C3

正确到sub bx, ax。但是,Turbo Assembler 将相同的指令 sub bx, ax 汇编为以下单词

2B D8

对此感到困惑,我发现this 参考说明从寄存器中减去寄存器确实可能以29 和2B 开头。真的是完全同一条指令可以用不同的操作码来表达吗?如果是这样,那是为什么?是因为历史原因和兼容性吗?参考说明了操作码的不同操作数类型,它们恰好与sub bx, ax 一致。这是为了以后通过自修改代码等修补不同操作数的能力吗?此外,Turbo Assembler 是否具有语法结构来选择一个操作码而不是另一个操作码?

注意: 我知道像 je 和 jz 这样的条件跳转具有相同的操作码,因为它们具有相同的标志相关行为,并且存在不同的助记符以反映不同的语义同样的操作,但前者让我感到困惑。

【问题讨论】:

    标签: assembly x86 tasm opcode instruction-encoding


    【解决方案1】:

    大多数 x86 指令支持两个操作数,其中一个操作数可以是内存操作数。这通过在 modr/m 字节中编码操作数来支持。这个字节总是编码一个寄存器操作数和一个寄存器或内存(r/m)操作数,但是指令必须决定它的操作数中哪个是寄存器操作数,哪个是内存操作数。

    因此,为了支持在源操作数或目标操作数中包含内存操作数,许多指令都可以使用一种变体,其中源操作数可以是内存操作数,而另一种变体可以将目标操作数作为内存操作数。这通常由位 01 控制(在某些手册中称为 d 位)。

    因此,不需要内存操作数的指令可以两种方式编码,而汇编程序通常会选择其中一种作为有点随机的实现细节。

    【讨论】:

    • 第一个字节的第 1 位是d 方向,您可以看到这是一个区别。在第二个字节中,比特 5-3 000 (AX) 和比特 2-0 011 (BX) 被交换。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-03
    • 2022-11-23
    • 1970-01-01
    • 2013-01-29
    相关资源
    最近更新 更多