WEB开发网
开发学院软件开发VC ATL布幔之下的秘密(4) 阅读

ATL布幔之下的秘密(4)

 2006-07-22 22:54:54 来源:WEB开发网   
核心提示: 如果你不希望修饰函数的名称,那么你可以对函数使用extern "C",ATL布幔之下的秘密(4)(2),让我们来对程序作少许修改,程序57. extern "C" void fun(int, int) {}int main() {fun(5, 10)

如果你不希望修饰函数的名称,那么你可以对函数使用extern "C"。让我们来对程序作少许修改。

程序57. extern "C" void fun(int, int) {
}
int main() {
 fun(5, 10);
 return 0;
}
调用函数的汇编代码为push 10  ; 0000000aH
push 5
call _fun
这就意味着现在你就不能对这个带有C链接方式的函数进行重载了。请看以下的程序

程序58. extern "C" void fun(int, int) {
}
extern "C" void fun(int, int, int) {
}
int main() {
 fun(5, 10);
 return 0;
}
这个程序会给出一个编译错误,因为函数的重载在C语言中是不支持的,并且你给两个函数起同样的名称的同时还告诉编译器不要修饰它的名字,也就是使用C的链接方式,而不是C++的链接方式。

现在来看看编译器为我们那个什么也不做的函数生成了什么,下面是编译器为我们的函数生成的代码。 push ebp
mov  ebp, esp
pop  ebp
ret  0
在我们进行详细地讲解之前,请看以下函数的最后一条语句,也就是ret 0。为什么是0?或者可以是别的非0数吗?正如我们所见,我们向函数传递的所有参数事实上都被压入了堆栈。在你或者编译器向堆栈中压入数据的时候,会对寄存器有什么影响吗?请看以下这个简单的程序来观察这一行为吧。我使用了printf而不是cout,这是为了避免cout的开销。

程序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
After push 1244976
这个程序显示了压栈前后ESP寄存器中的值。下图清楚地说明了在你向堆栈中压入数据后,ESP的值会减少。

上一页  1 2 3 4 5 6  下一页

Tags:ATL 之下 秘密

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接