我在工作中一直在使用免费的 Digital Mars 编译器(我知道很淘气),并创建了一些代码来检查编译的函数并查看字节码以用于学习目的,看看我是否可以从编译器的构建方式中学到任何有价值的东西它的功能。但是,在 MSVC++ 中重新创建相同的方法失败得很惨,我得到的结果非常混乱。我有这样的功能:
unsigned int __stdcall test()
{
return 42;
}
然后我做:
unsigned char* testCode = (unsigned char*)test;
在这种情况下,我似乎无法让 C++ static_cast 工作(它会引发编译器错误)......因此是 C 风格的强制转换,但这不是重点......我也尝试过使用参考 &test,但这无济于事。
现在,当我检查 testCode 指向的内存内容时,我感到很困惑,因为我看到的甚至看起来都不像有效代码,甚至还有一个调试断点卡在那里......它看起来像这样(目标是 IA -32):
0xe9, 0xbc, 0x18, 0x00, 0x00, 0xcc...
这显然是错误的,0xe9 是相对跳转指令,从 0xbc 字节外看是这样的:
0xcc,0xcc,0xcc……
即按照未分配或未使用内存的预期,内存初始化为调试断点操作码。
我对返回 42 的函数的期望是:
0x8b、0x2a、0x00、0x00、0x00、0xc3
或者至少一些 mov 的味道,然后是 ret (0xc2、0xc3、0xca 或 0xcb)再往下一点
MSVC++ 是出于安全原因采取措施阻止我做这种事情,还是我做了一些愚蠢的事情而没有意识到?使用 DMC 作为编译器,此方法似乎可以正常工作...
我也很难以另一种方式(执行字节),但我怀疑根本原因是相同的。
任何帮助或提示将不胜感激。