Lately, I've been writing some x86 assembly injections for the purpose of a game mod, but since most of my workflow has involved writing and assembling custom routines by hand, I've been looking to move towards a more robust solution.
Microsoft's inline assembler seems like a nice choice, but I've run into something of a limitation it seems to have.
Whenever I write an instruction that involves an immediate memory address (the game uses a fixed address space layout), the assembler silently converts it to an immediate value instead.
For example, in MASM:
mov ecx, 0xCCCCCCCC => B9 CC CC CC CC
mov ecx, [0xCCCCCCCC] => B9 CC CC CC CC*
* Should be: 8B 0D CC CC CC CC
In this case, both assembled instructions are loading ecx with the immediate value 0xCCCCCCCC, although the second one should be fetching the value from the immediate address 0xCCCCCCCC
Note that it's possible to use a named variable in this manner:
mov ecx, [myInt]
Which will assemble to an 8B 0D memory fetch instruction, but it also adds the operand to the module's relocation table and doesn't allow the specification of arbitrary addresses.
Trying to trick the assembler with something like
mov ecx, [myInt-myInt+0xCCCCCCCC]
Also results in the address being treated as an immediate value.
It is possible possible to go with:
mov ecx, 0xCCCCCCCC
mov ecx, [ecx]
Which will assemble properly and exhibit the correct behavior, but now I've bloated my injection size by 2 unnecessary bytes. Because I'm working under some rather tight spatial constraints, this isn't acceptable and I'd rather not use a code cave where I don't have to.
The funny thing is that something in C like:
register int x;
x = *(int*)(0xCCCCCCCC)
Happily compiles to
mov ecx, [0xCCCCCCCC] => 8B 0D CC CC CC CC
It's a little odd to see a lower level language have more limitations placed on it than a higher level language. What I'm trying to do seems pretty reasonable to me, so does anyone know if MASM has some hidden way of using fixed immediate memory addresses when reading from memory?