在这文章里面,我主要解释class里面的函数调用原理,首先给出测试代码如下:
class CBase{
public:
void Hello(){
}
};
int main(){
CBase base;
base.Hello();
}
同样地,按照前面文章讲解的方法,汇编得到以下main.asm,如下:
; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01
TITLE E:\bossjue\main.cpp
.686P
.XMM
include listing.inc
.model flat
INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES
PUBLIC ?Hello@CBase@@QAEXXZ ; CBase::Hello
PUBLIC _main
; Function compile flags: /Odtp
_TEXT SEGMENT
_base$ = -1 ; size = 1
_main PROC
; File e:\bossjue\main.cpp
; Line 7
push ebp
mov ebp, esp
push ecx
; Line 9
lea ecx, DWORD PTR _base$[ebp]
call ?Hello@CBase@@QAEXXZ ; CBase::Hello
; Line 10
xor eax, eax
mov esp, ebp
pop ebp
ret 0
_main ENDP
; Function compile flags: /Odtp
_TEXT ENDS
; COMDAT ?Hello@CBase@@QAEXXZ
_TEXT SEGMENT
_this$ = -4 ; size = 4
?Hello@CBase@@QAEXXZ PROC ; CBase::Hello, COMDAT
; _this$ = ecx
; Line 3
push ebp
mov ebp, esp
push ecx
mov DWORD PTR _this$[ebp], ecx
; Line 4
mov esp, ebp
pop ebp
ret 0
?Hello@CBase@@QAEXXZ ENDP ; CBase::Hello
_TEXT ENDS
END
对比上面我汇编汇编的非类的函数调用,你可以看到,无非是多了一个mov ecx, this的操作(等价的代码),其意思是把this复制给ecx,再调用函数,因此我们可以猜测,VS上的C++类函数调用是用ecx传递this指针(对stack没影响哦),我们写出如下测试代码,可以看到成功运行:
#include <iostream>
using namespace std;
class CBase{
public:
CBase(int iValue):m_iValue(iValue){}
public:
void Hello(){
cout<<m_iValue<<endl;
}
private:
int m_iValue;
};
int main(){
CBase base(100);
typedef void (CBase::*FunPtr)();
FunPtr FunAddr= &CBase::Hello;
__asm{
lea ecx, base
call FunAddr
}
}