c-函数指针地址与调试器显示的内容不一致



首先,如果这个问题显示出无知或我不知道什么,我深表歉意。我正在尝试读取函数地址下的指令,并且我已经通过检查编译器生成的.pdb文件来获得函数生成的代码大小。

但有一些东西让我困惑,看看下面的例子:

int function(int a, int b)
{
    return a + b;
}
int main(int argc, char* argv[])
{
    // (...)
    void* address = &function;
    function(10, 20);
    // (...)
}

对于调试器下的特定运行,我在void*地址中存储了0x00c011f4,VS的disassembly窗口相应地显示:

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*地址(0C011F4)指向的区域时,我没有得到与函数(int,int)下的asm指令相对应的机器代码。

提前感谢!

环境:Windows x64,VC10

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

您可以通过使用发布模式或禁用Edit&持续或者,你可以走长路线,只需分解跳跃(它应该是32位的相对跳跃),并使用跳跃的相对位移来调整地址。

最新更新