把函数体同调用相联系成为捆绑。但捆绑在运行前发生成为早捆绑。晚捆绑又称为动态捆绑或运行时捆绑。
c++代码为:
class base {
int i;
public:
virtual void print() {
}
};
class derived : public base {
int j;
public:
void print() {
}
virtual void print_another() {
}
};
int main()
{
base* b = new derived;
b->print();
return 0;
}
生成的汇编代码为:
TITLE D:\code\th_in_c++\pvdest\pvdest.cpp
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
$$SYMBOLS SEGMENT BYTE USE32 'DEBSYM'
$$SYMBOLS ENDS
$$TYPES SEGMENT BYTE USE32 'DEBTYP'
$$TYPES ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
; COMDAT ?print@base@@UAEXXZ
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
; COMDAT ?print@derived@@UAEXXZ
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
; COMDAT ?print_another@derived@@UAEXXZ
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
; COMDAT _main
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
; COMDAT ??0derived@@QAE@XZ
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
; COMDAT ??0base@@QAE@XZ
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
; COMDAT ??_7base@@6B@
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
; COMDAT ??_7derived@@6B@
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif
PUBLIC ??0derived@@QAE@XZ ; derived::derived
PUBLIC _main
EXTRN ??2@YAPAXI@Z:NEAR ; operator new
EXTRN ??3@YAXPAX@Z:NEAR ; operator delete
EXTRN __chkesp:NEAR
EXTRN __except_list:DWORD
EXTRN ___CxxFrameHandler:NEAR
; COMDAT xdata$x
; File D:\code\th_in_c++\pvdest\pvdest.cpp
xdata$x SEGMENT
__ehfuncinfo$_main DD 019930520H
DD 01H
DD FLAT:__unwindtable$_main
DD 2 DUP(00H)
DD 2 DUP(00H)
ORG $+4
__unwindtable$_main DD 0ffffffffH
DD FLAT:__unwindfunclet$_main
xdata$x ENDS
; COMDAT _main
_TEXT SEGMENT
_b$ = -16
$T270 = -20
$T271 = -24
__$EHRec$ = -12
_main PROC NEAR ; COMDAT
; File D:\code\th_in_c++\pvdest\pvdest.cpp
; Line 22
push ebp
mov ebp, esp
push -1
push __ehhandler$_main
mov eax, DWORD PTR fs:__except_list
push eax
mov DWORD PTR fs:__except_list, esp
sub esp, 80 ; 00000050H
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-92]
mov ecx, 20 ; 00000014H
mov eax, -858993460 ; ccccccccH
rep stosd
; Line 23
push 12 ; 0000000cH
call ??2@YAPAXI@Z ; operator new
add esp, 4
mov DWORD PTR $T271[ebp], eax
mov DWORD PTR __$EHRec$[ebp+8], 0
cmp DWORD PTR $T271[ebp], 0
je SHORT $L272
mov ecx, DWORD PTR $T271[ebp] //通过ecs将分配给derived对象b的地址传给构造函数
call ??0derived@@QAE@XZ ; derived::derived //调用构造函数
mov DWORD PTR -28+[ebp], eax //保存对象b的_this指针
jmp SHORT $L273
$L272:
mov DWORD PTR -28+[ebp], 0
$L273:
mov eax, DWORD PTR -28+[ebp] //将对象b的_this指针取到EAX
mov DWORD PTR $T270[ebp], eax //将EAX保存到$T270[ebp]中
mov DWORD PTR __$EHRec$[ebp+8], -1
mov ecx, DWORD PTR $T270[ebp] //_this指针取到ecs
mov DWORD PTR _b$[ebp], ecx //保存到_b$[ebp}内
; Line 24
mov edx, DWORD PTR _b$[ebp] //_this指针取到edx;
mov eax, DWORD PTR [edx] //该对象中存放的第一个数据vftable的地址取到eax
mov esi, esp //?
mov ecx, DWORD PTR _b$[ebp] //传递_this指针
call DWORD PTR [eax] //通过vftable中存放的print函数的地址调用print
cmp esi, esp //?
call __chkesp //?
; Line 25
xor eax, eax
; Line 26
mov ecx, DWORD PTR __$EHRec$[ebp]
mov DWORD PTR fs:__except_list, ecx
pop edi
pop esi
pop ebx
add esp, 92 ; 0000005cH
cmp ebp, esp
call __chkesp
mov esp, ebp
pop ebp
ret 0
_TEXT ENDS
; COMDAT text$x
text$x SEGMENT
__unwindfunclet$_main:
mov eax, DWORD PTR $T271[ebp]
push eax
call ??3@YAXPAX@Z ; operator delete
pop ecx
ret 0
__ehhandler$_main:
mov eax, OFFSET FLAT:__ehfuncinfo$_main
jmp ___CxxFrameHandler
text$x ENDS
_main ENDP
PUBLIC ??0base@@QAE@XZ ; base::base
PUBLIC ?print@derived@@UAEXXZ ; derived::print
PUBLIC ?print_another@derived@@UAEXXZ ; derived::print_another
PUBLIC ??_7derived@@6B@ ; derived::`vftable'
; COMDAT ??_7derived@@6B@
CONST SEGMENT
??_7derived@@6B@ DD FLAT:?print@derived@@UAEXXZ ; derived::`vftable'
DD FLAT:?print_another@derived@@UAEXXZ
CONST ENDS
; COMDAT ??0derived@@QAE@XZ
_TEXT SEGMENT
_this$ = -4
??0derived@@QAE@XZ PROC NEAR ; derived::derived, COMDAT
push ebp
mov ebp, esp
sub esp, 68 ; 00000044H
push ebx
push esi
push edi
push ecx
lea edi, DWORD PTR [ebp-68]
mov ecx, 17 ; 00000011H
mov eax, -858993460 ; ccccccccH
rep stosd
pop ecx
mov DWORD PTR _this$[ebp], ecx //对象存储区域的开始位置通过ecs传给_this指针
mov ecx, DWORD PTR _this$[ebp] //传递_this指针
call ??0base@@QAE@XZ ; base::base //调用base的构造函数进行初始化
mov eax, DWORD PTR _this$[ebp]