2012-02-14 18 views
2

首先 - 如果此问题显示无知或我不知道某事,我很抱歉。 我试图做一些事情,涉及读取函数的地址下的说明,我已经设法通过检查由编译器生成的.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的dissassembly窗口也相应显示:

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指令对应的机器码。

在此先感谢!

ENV:64位的Windows,VC10

回答

4

这是因为你已经编译在调试模式下的二进制文件,导致MSVC将通话和实际功能之间的中介跳跃(供编辑&继续)。所以你得到的地址(和程序集)是指向你的函数的跳转地址。

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

+0

顺便说一句 - 有没有一种方法可以确定Edit&Continue是否以实用的方式打开? – 2012-02-14 07:45:51

+1

@KarimA .:在pdb中可能有些东西,但除此之外我不知道。 – Necrolis 2012-02-14 08:15:29

+0

它首先是增量链接选项。 – 2012-02-14 08:58:41