3

In my function I use

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

which should produce the following bytes: 0x8B0D (mov ecx, dword ptr []). However the first instruction produces 0xB9 (mov ecx,0x28F14131) and the second one 0x3E:8B0D

So my question is, what instruction should I use to get the desired result inside the C++ __asm?

user2534466
  • 105
  • 1
  • 1
  • 5
  • Which compiler is this? It seems very strange that it changes from ecx to eax - compiler bug? – Mats Petersson Jul 28 '13 at 12:29
  • Oh sorry,that was a typo, fixed now, it comes to ecx but not ptr.. its VS2012 – user2534466 Jul 28 '13 at 12:43
  • 3
    It is a quirk in the 8086 instruction set that's not handled well by the inline assembler. The 0x0D byte encodes a displacement, not an address. Forcing the opcode with _asm _emit doesn't work either. Using the ds: override is as good as it gets for a workaround. – Hans Passant Jul 28 '13 at 13:02
  • So there is no way to get 0x8B0D without the 0x3E prefix using inline asm? – user2534466 Jul 28 '13 at 13:43
  • @HansPassant source? AFAIK a ModRM of 0D only encodes a displacement in 64bit mode, and then OP wouldn't be using inline asm in VS2012 because it refuses to do that in 64bit. – harold Jul 28 '13 at 15:25
  • Also, it's still encodable in 64bit, just slightly differently: `8B 8C 25 31 14 8F 02` (using a SIB with no index) – harold Jul 28 '13 at 15:34
  • Intel processor manual volume 2, chapter 2.1.3, table 2-2. Mod = 00, R/M = 101. And no, it is not a problem with the instruction. Documenting ancient bugs in compilers never makes anybody happy. – Hans Passant Jul 28 '13 at 15:34
  • @HansPassant ooh that, well they call it displacement everywhere, but a displacement relative to a non-present base is just an address – harold Jul 28 '13 at 15:36

1 Answers1

3

If you know for 100% certain what your byte sequence is supposed to be for your inlined assembly, you can always explicitly use those bytes. The exact syntax escapes me, but if you are using GCC, you may try ....

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

This approach only works if you know with 100% certainty what the byte sequences for the whole instruction are. AND if you are going to do this, be sure to comment appropriately.

(For what it is worth, I have had to use this approach in the past to work around a compiler bug where no matter what it would otherwise use the wrong byte sequence for one of the instructions.)

Sparky
  • 13,505
  • 4
  • 26
  • 27