【问题标题】:x86 Assembly 16-bit Relative Callx86 汇编 16 位相对调用
【发布时间】:2018-10-17 23:56:38
【问题描述】:

我注意到以下两个汇编指令在 x86 中可用:

E8 cw    CALL rel16
E8 cd    CALL rel32

我很困惑指令处理器如何区分这两个调用。我唯一能想到的是,如果应用程序是 16 位,则 IP 假定为前者,如果应用程序是 32 位,则 IP 假定为后者。我的解释是否正确,或者有没有办法将CALL rel16 编码为 32 位应用程序?

【问题讨论】:

  • 操作数大小(决定是rel16还是rel32)根据处理器的模式(realmode/32位保护模式/16位保护模式/64-位长模式/V8086 模式等)。你可以看到这个chart for details。您可以使用 0x66 操作数前缀覆盖默认值。在 32 位模式下,您可以使用 0x66 指令前缀将默认操作数大小从 32 位更改为 16 位
  • @MichaelPetch 所以如果我理解正确的话,我可以使用0x66E8YYYY(其中 66E8 是大端,而 YYYY 是小端),包含时将被解释为 CALL rel16在 32 位应用程序中。对吗?
  • 它将是 0x66 0xe8 0xYYYY 其中 0xYYYY 是小端相对值
  • 你没有询问副作用或它是如何工作的。您询问了编码。它清除了 EIP 的上半部分的事实已记录在案并且是设计使然。从 16 位相对调用的指令集参考中,它说 EIP tempEIP ← (EIP + DEST) AND 0000FFFFH; (* DEST 是 rel16 *) 。您会注意到高位设置为 0。您可以在此处读取 call 的 ISA:felixcloutier.com/x86/CALL.html
  • 使用 rel16 编码,您必须接受 EIP 处理方式的细微差别。除非您的所有代码都在该段的前 64KB 中,否则这种编码不是很有用。

标签: assembly x86 opcode


【解决方案1】:

此答案由 Michael Petch 在问题的 cmets 中提供:

操作数大小(决定是rel16还是rel32)有不同的默认大小取决于处理器的模式(实模式/32位保护模式/16位保护模式/64位长模式/V8086模式等)。你可以看到this chart for details。您可以使用 0x66 操作数前缀覆盖默认值。在 32 位模式下,您可以使用 0x66 指令前缀将默认操作数大小从 32 位更改为 16 位。

我注意到在使用该指令时,EIP 的高 16 位被清零。因此,0x66 0xE8 16 位相对调用具有以下 C++ 语义:

int16_t offset = ...;
EIP = (EIP + offset) & 0xFFFF;

所以是的,可以在 32 位应用程序中使用 16 位相对调用指令。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    • 2010-12-16
    • 1970-01-01
    • 2014-04-30
    • 2010-09-18
    • 2012-11-06
    相关资源
    最近更新 更多