ATL布幔之下的秘密(4)
2006-07-22 22:54:54 来源:WEB开发网程序64. extern "C" void _declspec(naked) fun() {
编译器生成的fun函数代码是类似于这个样子:
_asm ret
}
int main() {
fun();
return 0;
}_asm ret
这就意味着在这个函数中没有prolog代码和epilog代码。事实上,naked函数有一些规则,也就是你不能在naked函数中定义自动变量。因为如果你这么做的话,编译器就需要为你产生代码,而naked函数中编译器是不会产生任何代码的。其实,你还需要自己编写ret语句,否则程序就会崩溃。你甚至不能在naked函数中编写return语句。为什么呢?因为当你从函数中返回一些东西的时候,编译器就会把它的值放在eax寄存器之中。所以这就意味着编译器会为你的return语句产生代码。让我们通过下面的简单程序来弄懂函数返回值的工作过程吧。
程序64. #include <cstdio>
程序的输出为10。在这里我们并没有直接使用函数的返回值,而是在函数调用结束后将eax的值复制了一份。
extern "C" int sum(int a, int b) {
return a + b;
}
int main() {
int iRetVal;
sum(3, 7);
_asm mov iRetVal, eax
printf("%d\n", iRetVal);
return 0;
}
现在来编写我们的naked函数,这个函数没有prolog代码和epilog代码,它返回了两个变量的和。
程序65. #include <cstdio>
程序的输出为10,也就是两个参数3和7的和。
extern "C" int _declspec(naked) sum(int a, int b) {
// prolog代码
_asm push ebp
_asm mov ebp, esp
// 用于相加变量和返回的代码
_asm mov eax, dword ptr [ebp + 8]
_asm add eax, dword ptr [ebp + 12]
// epilog代码
_asm pop ebp
_asm ret
}
int main() {
int iRetVal;
sum(3, 7);
_asm mov iRetVal, eax
printf("%d\n", iRetVal);
return 0;
}
这一属性被用于ATLBASE.H中来实现_QIThunk结构的成员。这个结构被用于在定义了_ATL_DEBUG_INTERFACES的情况下调试ATL程序的引用计数。
我希望在下一篇文章中能够探究一些ATL的其它秘密。
更多精彩
赞助商链接