首先,如果这个问题显示出无知或我不知道什么,我深表歉意。我正在尝试读取函数地址下的指令,并且我已经通过检查编译器生成的.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位的相对跳跃),并使用跳跃的相对位移来调整地址。