I've been messing around with the free Digital Mars Compiler at work (naughty I know), and created some code to inspect compiled functions and look at the byte code for learning purposes, seeing if I can learn anything valuable from how the compiler builds its functions. However, recreating the same method in MSVC++ has failed miserably and the results I am getting are quite confusing. I have a function like this:
unsigned int __stdcall test()
{
return 42;
}
Then later I do:
unsigned char* testCode = (unsigned char*)test;
I can't seem to get the C++ static_cast to work in this case (it throws a compiler error)... hence the C-style cast, but that's besides the point... I've also tried using the reference &test, but that helps none.
Now, when I examine the contents of the memory pointed to by testCode I am confused because what I see doesn't even look like valid code, and even has a debug breakpoint stuck in there... it looks like this (target is IA-32):
0xe9, 0xbc, 0x18, 0x00, 0x00, 0xcc...
This is clearly wrong, 0xe9 is a relative jump instruction, and looking 0xbc bytes away it looks like this:
0xcc, 0xcc, 0xcc...
i.e. memory initialised to the debug breakpoint opcode as expected for unallocated or unused memory.
Where as what I would expect from a function returning 42 would be something like:
0x8b, 0x2a, 0x00, 0x00, 0x00, 0xc3
or at least some flavour of mov followed by a ret (0xc2, 0xc3, 0xca or 0xcb)a little further down
Is MSVC++ taking steps to prevent me from doing this sort of thing for security reasons, or am I doing something stupid and not realising it? This method seems to work fine using DMC as the compiler...
I'm also having trouble going the other way (executing bytes), but I suspect that the underlying cause is the same.
Any help or tips would be greatly appreciated.