2012-02-14 48 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