【问题标题】:Does MASM change instructions behind your back?MASM 会在你背后更改指令吗?
【发布时间】:2011-09-29 19:20:49
【问题描述】:

阅读HLA faq时,我对以下内容感到惊讶:

MASM 有一个讨厌的习惯,就是改变你背后的指令 背部。 HLA 似乎也有同样的问题。

然后我搜索了网络,但没有找到任何关于此的内容。这是真的还是只是一个神话?

【问题讨论】:

  • 不知道有任何具体情况,但它肯定可以。我知道旧的 A86 汇编器用于发出不同序列的兼容代码作为盗版检测机制的一部分。
  • 早期的 MASM 有点,呃,特别。如果您可以深入了解 tasm 中使用的 Borland QUIRKS 模式的详细信息,那么您会找到一个很好的列表。不过有点难,这是互联网之前的版本。

标签: assembly x86 x86-64 masm


【解决方案1】:

MASM 可以改变你的一切。例如,它可以修复您的条件跳转。也就是说,如果你写:

    add ax,bx
    jnz NotZero

    ...
NotZero:

如果NotZero 超出条件跳转范围,MASM 可以将您的代码重写为:

    add ax,bx
    jz Zero
    jmp NotZero
Zero:
    ...
NotZero:

我记得,有命令行开关可以防止这种情况发生。你也可以专门说,jnz near NotZero 来阻止它。如果你这样做并且目标在条件范围之外,你会得到一个错误。

我记得 MASM 做过一些其他类似的事情,但已经很久了。我不记得那些具体的东西是什么。

【讨论】:

    【解决方案2】:

    这有点半真半假。某些指令可以以不止一种方式进行编码,而且有时(出于他们从未解释过的原因)Microsoft 已经改变了它们对一些特定指令的编码方式。

    从第 6 版开始,它还具​​有多通道模式,可以/将使用“到达”目的地的最小跳跃形式对跳跃进行编码。在 5.x 之前,您必须手动指定近跳和远跳,如果您猜错了,在第二次通过时会产生“相位错误”。从 v6 开始,它会自动调整大小。由于这会改变指令的大小,这可能会迫使其他周围的跳转也发生变化(同样,在另一个方向上,一个较小的跳转编码可能会减少另一个跳转可以用较小的编码到达它的目的地的代码大小)。

    不是,然而,从大多数人的角度来看,这是一个“讨厌的习惯”——恰恰相反,大多数人更喜欢它尽可能高效地自动编码指令。有一些情况(例如,自我修改代码)您需要防止它,但那些通常被称为“讨厌的习惯”(至少如果你真的习惯性地这样做的话) .

    【讨论】:

    • 这么多好答案,但由于我必须选择一个,所以我选择了这个,对不起其他人。
    【解决方案3】:

    这可能不是您想要的,但我遇到过 MASM 不会为相同的输入生成与其他类似汇编程序(例如 NASM)相同的输出的情况。也就是说,一个稍微不同的字节序列反汇编成相同的东西。

    通常,这根本不是问题,我什至注意到它的唯一原因是因为一个奇怪的情况,我需要指令中的某些位作为特定值;使用一个汇编程序很好,而使用另一个汇编程序就不行了,我不得不手动进行修复。

    希望对您有所帮助。

    【讨论】:

    • "也就是说,一个稍微不同的字节序列反汇编成同一个东西。" 哇,我不知道这样的事情是可能的吗?我以为汇编语言和机器语言之间存在一对一的映射关系。
    • 不,这很少见。一个与我描述的不太一样的简单示例,但应该足够了:尝试在 nasm 中组装 int3int 3。你应该分别得到类似\xcc\xcc03 的东西。有趣的事实:一些调试器在解析后者时遇到问题(因为他们期望单字节指令)。玩得开心!
    • 我相信一些 MOV 甚至可能是 ADD 指令有不止一种二进制编码可以做同样的事情。只是凭记忆,自从我处理这个问题以来已经很久了。 :-)
    【解决方案4】:

    我认为这种“变化”与指令调度和窥视孔优化有关。当您使用“cat >pgm.o”编写代码时,您可以避免这种情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-11-01
      • 2019-10-11
      • 1970-01-01
      • 2016-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多