C++ __asm 生成不同字节

3

在我的函数中,我使用

__asm
{
  mov     ecx,dword ptr [0x28F1431]
  mov     ecx,ds:[0x28F14131]
}

应该生成以下字节:0x8B0Dmov ecx,dword ptr [])。 然而第一条指令生成 0xB9mov ecx,0x28F14131),第二条指令生成 0x3E:8B0D。

我的问题是,在 C++ 的 __asm 中,我应该使用什么指令来获得所需的结果?


这是哪个编译器?它似乎非常奇怪,从ecx变成eax - 编译器bug? - Mats Petersson
3
8086指令集中存在一个怪癖,这种怪癖在内联汇编程序中处理得不好。0x0D字节编码了一个位移量而不是一个地址。即使使用_asm _emit强制生成操作码也无法解决此问题。使用ds: 段寄存器的重载就是解决此问题的最佳方法。 - Hans Passant
此外,它仍然可以以64位编码,只是略有不同:8B 8C 25 31 14 8F 02(使用没有索引的SIB)。 - harold
英特尔处理器手册第2卷,第2.1.3章,表2-2。Mod = 00,R/M = 101。不,这不是指令的问题。记录编译器中古老的错误从来不会让任何人感到快乐。 - Hans Passant
@HansPassant 噢,那个,他们在任何地方都称之为位移,但相对于不存在的基址的位移只是一个地址。 - harold
显示剩余3条评论
1个回答

3

如果您确定内联汇编的字节序列是100%正确的,那么您可以始终明确使用这些字节。具体的语法我不太清楚,但如果您正在使用GCC,可以尝试....

__asm {
    .byte 0x##
    .byte 0x##
    ...
}

这种方法只有当你完全确定整个指令的字节序列时才有效。如果要这样做,请确保适当地进行注释。(值得一提的是,过去我曾经不得不使用这种方法来解决编译器错误的问题,在这种情况下,无论如何它都会使用一个指令的错误字节序列。)

在 MSVC 下,您可以使用 __emit 将字节放入汇编输出流中。 - Necrolis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接