ATL布幔之下的秘密(4)
2006-07-22 22:54:54 来源:WEB开发网如果你不希望修饰函数的名称,那么你可以对函数使用extern "C"。让我们来对程序作少许修改。
程序57. extern "C" void fun(int, int) {
调用函数的汇编代码为
}
int main() {
fun(5, 10);
return 0;
}push 10 ; 0000000aH
这就意味着现在你就不能对这个带有C链接方式的函数进行重载了。请看以下的程序
push 5
call _fun
程序58. extern "C" void fun(int, int) {
这个程序会给出一个编译错误,因为函数的重载在C语言中是不支持的,并且你给两个函数起同样的名称的同时还告诉编译器不要修饰它的名字,也就是使用C的链接方式,而不是C++的链接方式。
}
extern "C" void fun(int, int, int) {
}
int main() {
fun(5, 10);
return 0;
}
现在来看看编译器为我们那个什么也不做的函数生成了什么,下面是编译器为我们的函数生成的代码。 push ebp
在我们进行详细地讲解之前,请看以下函数的最后一条语句,也就是ret 0。为什么是0?或者可以是别的非0数吗?正如我们所见,我们向函数传递的所有参数事实上都被压入了堆栈。在你或者编译器向堆栈中压入数据的时候,会对寄存器有什么影响吗?请看以下这个简单的程序来观察这一行为吧。我使用了printf而不是cout,这是为了避免cout的开销。
mov ebp, esp
pop ebp
ret 0
程序59. #include <cstdio>
程序的输出为:
int g_iTemp;
int main() {
fun(5, 10); // 译注:这里的fun,应该是上文中的void fun(int, int)
_asm mov g_iTemp, esp
printf("Before push %d\n", g_iTemp);
_asm push eax
_asm mov g_iTemp, esp
printf("After push %d\n", g_iTemp);
_asm pop eax
return 0;
}Before push 1244980
这个程序显示了压栈前后ESP寄存器中的值。下图清楚地说明了在你向堆栈中压入数据后,ESP的值会减少。
After push 1244976
更多精彩
赞助商链接