调试器显示的函数指针地址不一致

时间:2012-02-14 06:50:43

标签: c memory assembly portable-executable

首先 - 如果这个问题显示无知或者我不知道某事,我道歉。 我正在尝试做一些涉及在函数地址下读取指令的内容,并且我已经设法通过检查编译器生成的.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

1 个答案:

答案 0 :(得分:4)

这是因为您已在调试模式下编译二进制文件,导致MSVC在调用和实际函数之间进行中间跳转(供Edit& Continue使用)。因此,您获得的地址(和程序集)是指向您的函数的跳转地址。

您可以使用发布模式或禁用编辑&amp ;;继续。或者你可以采取漫长的路线,只需反汇编跳跃(它应该是一个32位的相对跳跃),并使用跳跃的相对位移来调整地址。