首先 - 如果这个问题显示无知或者我不知道某事,我道歉。 我正在尝试做一些涉及在函数地址下读取指令的内容,并且我已经设法通过检查编译器生成的.pdb文件来获取函数生成的代码大小。
但是有些东西让我困惑,请看下面的例子:
int function(int a, int b)
{
return a + b;
}
int main(int argc, char* argv[])
{
// (...)
void* address = &function;
function(10, 20);
// (...)
}
对于调试器下的特定运行,我将0x00c011f4存储在void *地址中,VS的反汇编窗口也相应显示:
int main(int argc, char* argv[])
{
00C04B00 push ebp
00C04B01 mov ebp,esp
00C04B03 sub esp,178h
00C04B09 push ebx
00C04B0A push esi
00C04B0B push edi
00C04B0C lea edi,[ebp-178h]
00C04B12 mov ecx,5Eh
00C04B17 mov eax,0CCCCCCCCh
00C04B1C rep stos dword ptr es:[edi]
void* address = &function;
00C04B1E mov dword ptr [address],offset function (0C011F4h)
function(10, 20);
00C04B25 push 14h
00C04B27 push 0Ah
00C04B29 call function (0C011F4h)
00C04B2E add esp,8
根据00C04B1E下的指令,对应于function
开头的地址低于0C011F4 - 这正是存储在void *地址中的地址。
现在单步执行调试器并按照跳转到函数(int,int)给出以下反汇编:
int function(int a, int b)
{
00C019C0 push ebp
00C019C1 mov ebp,esp
00C019C3 sub esp,0C0h
00C019C9 push ebx
00C019CA push esi
00C019CB push edi
00C019CC lea edi,[ebp-0C0h]
00C019D2 mov ecx,30h
00C019D7 mov eax,0CCCCCCCCh
00C019DC rep stos dword ptr es:[edi]
return a + b;
00C019DE mov eax,dword ptr [a]
00C019E1 add eax,dword ptr [b]
}
00C019E4 pop edi
00C019E5 pop esi
00C019E6 pop ebx
00C019E7 mov esp,ebp
00C019E9 pop ebp
00C019EA ret
这里函数(int,int)的求求低于0x00C019C0。这是为什么?这是1996年的字节。我试图找到任何相关性,但我认为我在这里缺少一些基本的东西。有人可以告诉我为什么这两个地址不同?
当我复制void * address(0C011F4)指向的区域时,我没有得到与函数(int,int)下的asm指令对应的机器代码。
提前致谢!
环境:Windows x64,VC10
答案 0 :(得分:4)
这是因为您已在调试模式下编译二进制文件,导致MSVC在调用和实际函数之间进行中间跳转(供Edit& Continue使用)。因此,您获得的地址(和程序集)是指向您的函数的跳转地址。
您可以使用发布模式或禁用编辑&amp ;;继续。或者你可以采取漫长的路线,只需反汇编跳跃(它应该是一个32位的相对跳跃),并使用跳跃的相对位移来调整地址。