一,C语言中函数的调用方式
没有理解虚拟函数在内存中的处理形式,我觉得是自己在看书的时候缺乏思考造成的,只是跟着书本走,但没有仔细去想相关的内容。所以造成了思维闭路,导致很多东西理解错误。我觉得理解虚函数,还得从对函数在代码中的组织形式开始。好了,先谈谈我对函数的理解吧。
我们知道一个可执行有数据段,代码段等来存储文件的执行信息。而汇编就是用这种格式来写代码的,高级语言如C等都需要把文件转化为汇编之后,进行编译,最终生成可执行文件。所以把C文件转化为汇编,可能能更好的理解代码的组织形式。
我们先来看一段简单的C文件:
Void first()
{
}
Void main()
{
frist();
}
在main中是通过何种形式来调用first的呢?学过汇编的话,我们知道汇编 中的函数的调用是通过call指令来实现的。试着编译以上的C程序,并通过dumpbin反编译它的exe文件,我们可以得到以下一段代码。
00401000: CC int 3
00401001: CC int 3
00401002: CC int 3
00401003: CC int 3
00401004: CC int 3
@ILT+0(_first):
00401005: E9 16 00 00 00 jmp _first
@ILT+5(_main):
0040100A: E9 41 00 00 00 jmp _main
0040100F: CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC ìììììììììììììììì
0040101F: CC ì
_first:
00401020: 55 push ebp
00401021: 8B EC mov ebp,esp
00401023: 83 EC 40 sub esp,40h
00401026: 53 push ebx
00401027: 56 push esi
00401028: 57 push edi
00401029: 8D 7D C0 lea edi,[ebp-40h]
0040102C: B9 10 00 00 00 mov ecx,10h
00401031: B8 CC CC CC CC mov eax,0CCCCCCCCh
00401036: F3 AB rep stos dword ptr [edi]
00401038: 5F pop edi
00401039: 5E pop esi
0040103A: 5B pop ebx
0040103B: 8B E5 mov esp,ebp
0040103D: 5D pop ebp
0040103E: C3 ret
0040103F: CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC ìììììììììììììììì
0040104F: CC ì
_main:
00401050: 55 push ebp
00401051: 8B EC mov ebp,esp
00401053: 83 EC 40 sub esp,40h
00401056: 53 push ebx
00401057: 56 push esi
00401058: 57 push edi
00401059: 8D 7D C0 lea edi,[ebp-40h]
0040105C: B9 10 00 00 00 mov ecx,10h
00401061: B8 CC CC CC CC mov eax,0CCCCCCCCh
00401066: F3 AB rep stos dword ptr [edi]
00401068: E8 98 FF FF FF call @ILT+0(_first)
0040106D: 5F pop edi
0040106E: 5E pop esi
0040106F: 5B pop ebx
00401070: 83 C4 40 add esp,40h
00401073: 3B EC cmp ebp,esp
00401075: E8 16 00 00 00 call __chkesp
0040107A: 8B E5 mov esp,ebp
0040107C: 5D pop ebp
0040107D: C3 ret
0040107E: CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC ìììììììììììììììì
0040108E: CC CC ìì