冰天雪地旋转365度裸体跪求关于 函数调用 的一个小问题
如下测试代码
void fun()
{
}
int main(int argc, _TCHAR* argv[])
{
fun(); // 把断点设在此处,打开vc的汇编调式页面单步跟踪
return 0;
}
------------------------
我发现fun的调用过程是这样的
fun();
004117FE call fun (411109h) // 这里继续按f11单步跟踪
然后到
00411109 jmp fun (411380h) // 再f11单步跟踪
然后到
void fun() // 这个时候才到真正的fun函数里
{
00411380 push ebp
00411381 mov ebp,esp
00411383 sub esp,0C0h
00411389 push ebx
............
我的疑问是中间为什么要多一个 jmp 跳转,然后再跳到fun里呢
所以当用
DWORD dwp = (DWORD)fun;
得到的地址并不是fun函数的真正的地址,而是那条jmp指令的地址
为什么会这样的
如果是系统API的调用就不会这样,而是直接跳到函数里,没有这个jmp
我底层的东西很菜,大家指教啊,特别是虫子,不要进来就走啊
[解决办法]
- -我在vs.net 2003下面看到的不一样……call之后直接转到函数的地址
fun(); // 把断点设在此处,打开vc的汇编调式页面单步跟踪
0040163E call fun (4015F0h)
void fun()
{
004015F0 push ebp
004015F1 mov ebp,esp
004015F3 sub esp,0C0h
004015F9 push ebx
004015FA push esi
004015FB push edi
004015FC lea edi,[ebp-0C0h]
00401602 mov ecx,30h
00401607 mov eax,0CCCCCCCCh
0040160C rep stos dword ptr [edi]
}
[解决办法]
Release Build下没有这步jmp, Debug下多这步可能是为了调试吧(至于究竟对调试有什么好处偶也不知道了 -_- )
[解决办法]
好恶心~
这个是PE文件的特性,在访问函数(一般是系统函数时)系统会导入相对应的API所在的DLL,并且在PE文件的输入表中记录其,在运行前期,系统的PELOADER会装载该PE文件,填入输入表实际的函数地址(DLL动态调入内存,其函数地址未知,所以此时才确定)同时改写Import Address Table(IAT)那里就是IAT使用反汇编器(如W32DASM)反汇编一个程序可以看到,所有API调用都要这样JMP 一个指向IAT表格中此函数的入口点。
装载机装载时修改这些入口点以匹配实际内存函数的地址。
当然这些仅仅限于调入函数(外部的DLL和API),一般程序自己的函数不这样,这就是DEBUG和RELEASE一大区别之一编译器DEBUG时候这样也是为了修改PE文件的方便~
[解决办法]
VC在处理C++的时候都是在前面做了一个函数列表,这样做可以很好的使用VTable,详情你可以参考CSDN一个朋友写的《C++虚函数表反汇编》——名字忘记了,大概就是这个意思。
[解决办法]
星星就是星星啊,不服不行啊,整篇代码基本没看懂...纯顶,学习
[解决办法]
函数名标记都是用地址的
但使用的地方不同,所以就用跳转
所以要用jmp了
[解决办法]
程序反汇编:
;main()开始
* Reference To: KERNEL32.GetTickCount, Ord:016Dh
|
;这里直接使用了地址,没有用表查询,说明确定地址,不用查询了,KERNEL32必定装入了内存,所以没有必要查询,但是表结构还是存在的~
:0040102A FF15B0A14200 Call dword ptr [0042A1B0]
:00401030 3BF4 cmp esi, esp
:00401032 E829000000 call 00401060
:00401037 33C0 xor eax, eax
:00401039 5F pop edi
:0040103A 5E pop esi
:0040103B 5B pop ebx
:0040103C 83C440 add esp, 00000040
:0040103F 3BEC cmp ebp, esp
:00401041 E81A000000 call 00401060
:00401046 8BE5 mov esp, ebp
:00401048 5D pop ebp
:00401049 C3 ret
:0040104A CC int 03
:0040104B CC int 03
:0040104C CC int 03
:0040104D CC int 03
:0040104E CC int 03
:0040104F CC int 03
:00401050 CC int 03
:00401051 CC int 03
:00401052 CC int 03
:00401053 CC int 03
:00401054 CC int 03
:00401055 CC int 03
:00401056 CC int 03
:00401057 CC int 03
;这里开始都是表结构,只是GetTickCount没有使用罢了
* Reference To: KERNEL32.GetTickCount, Ord:016Dh
|
:00401058 FF25B0A14200 Jmp dword ptr [0042A1B0]
:0040105E CC int 03
:0040105F CC int 03
;这个是平衡堆栈的系统函数的表,用到了
* Referenced by a CALL at Addresses:
|:00401032 , :00401041
|
:00401060 7501 jne 00401063
:00401062 C3 ret
[解决办法]
冲着裸体来的,,,,想,,,,
VC中,会生成一个函数的符号以及函数实际地址的对应表。当调用1个函数时,先得到的是函数的符号地址,而这些符号地址里面都是对应1个跳转指令,指向函数的实际地址。