main函数声明
main函數(shù)聲明
?
背景:
main函數(shù)經(jīng)常會聲明為以下方式:
int main(); int main(int argc, char* argv[]); int main(int argc, char* argv[], char*envp[]);還有些會將返回類型替換為void,最常見的就是
void main();?
一、VC如何支持這些不同的main函數(shù)聲明
main函數(shù)是在__tmainCRTStartup中被調(diào)用的,__tmainCRTStartup也沒有做特別處理。
不同main函數(shù)聲明被支持是因為main函數(shù)是使用__cdecl調(diào)用約定的。
__cdecl調(diào)用約定由調(diào)用方負責(zé)參數(shù)的壓棧和出棧。
__tmainCRTStartup實現(xiàn)在crtexe.c中,其調(diào)用main函數(shù)的匯編碼如下:
mainret = main(argc, argv, envp); 00A4BAEF mov eax,dword ptr [envp (0A572B0h)] 00A4BAF4 push eax 00A4BAF5 mov ecx,dword ptr [argv (0A572B4h)] 00A4BAFB push ecx 00A4BAFC mov edx,dword ptr [argc (0A572ACh)] 00A4BB02 push edx 00A4BB03 call @ILT+1355(_main) (0A41550h) 00A4BB08 add esp,0Ch 00A4BB0B mov dword ptr [mainret (0A572C4h)],eax?
__tmainCRTStartup做如下處理:
1、按從右到左的順序?qū)⑷齻€參數(shù)壓棧
2、調(diào)用main函數(shù)
3、出棧 (簡單的將棧指針移上來,上移是因為棧是向下生長的)
4、將存放在eax中的返回值賦給int型的mainret
以下聲明也是合法的:
int main(int a, int b, char* c, int d, char* e);PS:關(guān)于為什么__tmainCRTStartup調(diào)用的main原型與聲明的不一致也能通過編譯和鏈接是因為__tmainCRTStartup已經(jīng)是編譯過的,對于函數(shù)原型的檢查是在編譯期執(zhí)行的,鏈接時只需要VC鏈接器能找到main函數(shù)符號即可。
二、void替換int,有什么影響
有如下main函數(shù)
void main() {printf("Hello, world!\n"); }?
其匯編代碼如下:
printf("Hello, world!\n"); 00A4D70E mov esi,esp 00A4D710 push offset string "Hello, world!\n" (0A53894h) 00A4D715 call dword ptr [__imp__printf (0A586FCh)] 00A4D71B add esp,4 00A4D71E cmp esi,esp 00A4D720 call @ILT+1335(__RTC_CheckEsp) (0A4153Ch) } 00A4D725 xor eax,eax 00A4D727 pop edi 00A4D728 pop esi 00A4D729 pop ebx 00A4D72A add esp,0C0h 00A4D730 cmp ebp,esp 00A4D732 call @ILT+1335(__RTC_CheckEsp) (0A4153Ch) 00A4D737 mov esp,ebp 00A4D739 pop ebp 00A4D73A ret編譯器會補上xor eax,eax ,返回值放在eax中。
也就是說void替換int后,該函數(shù)返回值就是0,不能返回其它值了。其他代碼使用GetExitCodeProcess()獲取該進程的退出代碼時,只能得到0,不具備指示意義。
?
轉(zhuǎn)載于:https://www.cnblogs.com/shokey520/p/3673880.html
總結(jié)
- 上一篇: Grails精华:使用Groovy SQ
- 下一篇: SQL语句学习之路3