两个吃奶一个添下面视频_人妻第一页香蕉网_欧美xxxx少妇_妺妺窝人体色www婷婷

  • 歡迎訪問C語言網(wǎng)www.sztianhecheng.cn 比賽欄每月有獎(jiǎng)月賽!舉辦比賽聯(lián)系QQ:2045302297
  • 問題反饋、粉絲交流 QQ群327452739 藍(lán)橋杯訓(xùn)練群:113766799 申請(qǐng)群時(shí)請(qǐng)備注排名里的昵稱
  • C語言研究中心 為您提供有圖、有料、解渴的C語言專題! 歡迎討論!

C語言程序真正的啟動(dòng)函數(shù)

C語言研究中心 CTO 20915次瀏覽 6個(gè)評(píng)論

 

為什么要用”真正”這個(gè)詞?因?yàn)槲覀儚膶W(xué)C語言開始,都會(huì)先明白這個(gè)道理,即C語言有且僅有一個(gè)main函數(shù),main函數(shù)是C語言的入口點(diǎn)和出口點(diǎn)?。梢?/span>參考<<一個(gè)C語言程序的基本機(jī)構(gòu)>>)不光C語言如此,C++也如此,甚至無論黑窗口的控制臺(tái)程序和Windows應(yīng)用程序,都是從main函數(shù)或者WinMain函數(shù)開始執(zhí)行,這當(dāng)然沒錯(cuò),但事實(shí)上main函數(shù)僅僅是一個(gè)C語言語法規(guī)定的入口點(diǎn),而不是真正的程序入口,因?yàn)樗灿泻瘮?shù)返回值!它也需要被調(diào)用!所以,今天我們將帶大家去揭秘main函數(shù)之前的代碼,去看看真正的啟動(dòng)函數(shù)是什么!來讓大家深入理解C語言程序,方便大家日后的逆向?qū)W習(xí)!

 

由于大多數(shù)情況下,我們?cè)赩C環(huán)境下,常常C/C++混編,或控制臺(tái)程序和windows應(yīng)用程序都有接觸,同時(shí)會(huì)因?yàn)榫幋a方式的區(qū)分如ANSI或者Unicode編碼啟動(dòng)函數(shù)還各不相同,為保持簡單、純粹。我們今天僅僅討論ANSI編碼控制臺(tái)程序下純C語言的程序入口分析。

 

事實(shí)上,在VC6編譯器下,ANSI編碼環(huán)境下C語言的真正啟動(dòng)函數(shù)名叫做mainCRTStarup,英語好的同學(xué)應(yīng)該可以明白一些,Starup就是初始化、啟動(dòng)的意思,其實(shí)也可以根據(jù)這點(diǎn)明白這個(gè)函數(shù)作用就是在C語言啟動(dòng)之前做一些必要的工作,如堆棧初始化、獲得主函數(shù)的參數(shù)等等。

還是本著我們“實(shí)踐教學(xué)”的原則,我們還是以實(shí)踐、做實(shí)驗(yàn)來驗(yàn)證和理解我們的知識(shí),由于關(guān)系到函數(shù)間調(diào)用的關(guān)系,我們應(yīng)該聯(lián)想到VC6編譯器帶給我們的?;厮莨δ堋S信d趣的同學(xué)可以參考?? VC6斷點(diǎn)調(diào)試之窗口監(jiān)視(內(nèi)存監(jiān)視、寄存器和棧回溯)<第五篇>

 

依次View – Debug Windows-> Call Stack

通過編譯器提供的?;厮莨δ芸梢钥吹匠绦騿?dòng)后的調(diào)用過程,如下如:

C語言程序真正的啟動(dòng)函數(shù)

通過斷點(diǎn)提示,我們看到目前程序位于main函數(shù)第四行??梢钥吹缴弦淮问潜籱ainCRTStartup函數(shù)調(diào)用,在第206行的25個(gè)字節(jié)偏移處開始調(diào)用,再之前就是KERNEL32了,它是windows系統(tǒng)三大主要文件之一。軟件系統(tǒng)層面的調(diào)用就到此為止了。

因?yàn)榇蠖鄶?shù)逆向分析工具基本都會(huì)從這里開始,所以我們也重點(diǎn)研究mainCRTStartup函數(shù)的原理。幸運(yùn)的是,VC6編譯器為我們提供了mainCRTStartup函數(shù)的源碼,但需要大家安裝完整版才可以看到,不然只能看到反匯編代碼。

 

這里我們摘錄一部分主要的mainCRTStartup代碼,供大家參考學(xué)習(xí):

 

//預(yù)編譯宏
#else /*_WINMAIN_*/
#ifdef WPRFLAG
//寬字符版控制臺(tái)啟動(dòng)函數(shù)
void wmainCRTStartup(
#else/*WPRFLAG*/
//多字節(jié)版控制臺(tái)啟動(dòng)函數(shù)
void mainCRTStartup(
#endif /*WPRFLAG*/
#endif /*_WINMAIN_*/
void )
{
//獲取系統(tǒng)版本信息
_osver=GetVersion();
_winminor=(_oserver>>8)&0x00FF;
_winmajor=_oserver & 0xFF; //主版本
_winver=(_winmajor<<8)+_winminor; _osver=(_osver>>16) & 0x00FFFF;
//堆空間初始化過程,在這個(gè)函數(shù)里,指定了程序中堆空間的起始地址
//_MT是多線程標(biāo)記
#ifdef _MT
if(!_heap_init(1))
#else /*_MT*/
if(!_heap_intit(0))
#endif /*_MT*/
fast_error_exit(_RT_HEAPINIT);
//初始化多線程環(huán)境
#ifdef _MT
if(!_mtinit())
fast_error_exit(_RT_THREAD);
#endif /*_MT*/
_try{
//寬字符處理代碼略
//多字節(jié)版獲取命令行
_acmdln=(char*)GetCommandLineA();
//多字節(jié)版獲取環(huán)境變量信息
_aenvptr=(char*)_crtGetEnvironmentStringsA();
//多字節(jié)版獲取命令行信息
_setargv();
//多字節(jié)版獲取環(huán)境變量信息
_setenvp();
#endif /*WPRFLAG*/
//初始化全局?jǐn)?shù)據(jù)和浮點(diǎn)寄存器
_cinit();
//窗口程序處理代碼略
//寬字符串里代碼略
//獲取環(huán)境變量信息
_initenv=_environ;
//調(diào)用main函數(shù),傳遞命令行參數(shù)信息
mainret=main(_argc,_argv,_environ);
#endif /*WPRFLAG*/
#endif/*_WINMAIN_*/
//檢查main函數(shù)返回值執(zhí)行析構(gòu)函數(shù)或atexit注冊(cè)函數(shù)指針,并結(jié)束程序
exit(mainret)
}
//退出結(jié)束代碼略
}

以上語法依舊是C語言,大家可以自行對(duì)照注釋進(jìn)行理解,熟悉main函數(shù)在調(diào)用前的一些準(zhǔn)備工作,可以總結(jié)如下:

1.GetVersion函數(shù):獲取當(dāng)前運(yùn)行平臺(tái)的版本號(hào)??刂婆_(tái)下則為MS-DOS的版本信息。

2._heap_init函數(shù):用于初始化堆空間。在函數(shù)實(shí)現(xiàn)中使用HeapCreate申請(qǐng)堆空間

3.GetCommandLineA函數(shù):獲取命令行參數(shù)信息的首地址

4._crtGetEnvironmentStringA函數(shù):獲取環(huán)境變量信息的首地址

5._setargv函數(shù):此函數(shù)根據(jù)GetCommandLineA獲取命令行參數(shù)信息的首地址并進(jìn)行參數(shù)分析 注意主函數(shù)的參數(shù)就在這里獲得!

6._setenvp函數(shù):此函數(shù)根據(jù)_crtGetEnvironmentStringA函數(shù)獲取環(huán)境變量信息的首地址進(jìn)行分析。

7._cinit函數(shù):用于全局變量數(shù)據(jù)和浮點(diǎn)數(shù)寄存器的初始化。

 

大家可以對(duì)比代碼加注釋深入理解main函數(shù)啟動(dòng)前的準(zhǔn)備工作,來加深程序啟動(dòng)的機(jī)制理解。

通過觀察,在_cinit()函數(shù)之后,我們可以看到有主函數(shù)的調(diào)用語句mainret = main(_argc,_argv,_environ),現(xiàn)在知道主函數(shù)的返回值給誰了吧?

 

至此,我們最熟悉的main函數(shù)就出現(xiàn)了,怎么樣,大家連起來了嗎?

 

如果還能理解,我們接下來做一個(gè)更改入口函數(shù)的實(shí)驗(yàn),來加深大家的學(xué)習(xí)。如下:

編譯器工具欄 Project – Setting – Link – Output 如下圖:

C語言程序真正的啟動(dòng)函數(shù)

在入口點(diǎn)出輸入你想自定義的函數(shù)名,比如起名MyDotcpp,將替換掉mainCRTStartup函數(shù),重新被KERNEL32調(diào)用,main函數(shù)作為C語言語法入口點(diǎn),被MyDotcpp調(diào)用,如圖:

C語言程序真正的啟動(dòng)函數(shù)

重新打開棧回溯查看調(diào)用情況,可以看到入口函數(shù)已經(jīng)被更改掉了

C語言程序真正的啟動(dòng)函數(shù)

 

當(dāng)然,這里我們定義的MyDotcpp函數(shù)僅僅用來測試更改入口函數(shù),正如mainCRTStartup之前描述的代碼一般,入口函數(shù)擁有更多的比如初始化堆空間、浮點(diǎn)數(shù)等功能,如果我們這里在多加一些如開辟內(nèi)存等語句,運(yùn)行將會(huì)報(bào)錯(cuò),大家可以親自上機(jī)嘗試。

 

以上就是關(guān)于程序真正的入口函數(shù)的介紹,請(qǐng)大家好好消化!

 

在閱讀本文和學(xué)習(xí)過程中,大家本機(jī)實(shí)際情況可能和截圖不一致,歡迎大家留言交流、討論!

如有問題,歡迎糾正!

 

C語言網(wǎng)提供「C語言、C++、算法競賽」在線課程,全部由資深研發(fā)工程師或ACM金牌大佬親授課,更科學(xué)、全面的課程體系,以在線視頻+在線評(píng)測的學(xué)習(xí)模式學(xué)習(xí),學(xué)練同步,拒絕理論派,真正學(xué)會(huì)編程!還有獎(jiǎng)學(xué)金等增值福利等你!

C語言網(wǎng), 版權(quán)所有丨如未注明 , 均為原創(chuàng)丨本網(wǎng)站采用BY-NC-SA協(xié)議進(jìn)行授權(quán) , 轉(zhuǎn)載請(qǐng)注明C語言程序真正的啟動(dòng)函數(shù)!
喜歡 (56)
[jinyangH@aliyun.com]
分享 (0)
發(fā)表我的評(píng)論
取消評(píng)論
表情

Hi,您需要填寫昵稱和郵箱!

  • 昵稱 (必填)
  • 郵箱 (必填)
(6)個(gè)小伙伴在吐槽
  1. 看到這么好的文章沒有人評(píng)論,好可惜啊。點(diǎn)贊
    yuliner2017-03-21 21:42 回復(fù)
    • 謝謝支持!! 看到的人比較少吧,多多分享吧!
      CTO2017-03-29 10:36 回復(fù)
  2. “如果我們這里在多加一些如開辟內(nèi)存等語句,運(yùn)行將會(huì)報(bào)錯(cuò)” 博主說的是在main()函數(shù)里面開辟內(nèi)存會(huì)報(bào)錯(cuò)么?(因?yàn)樽远x的啟動(dòng)函數(shù)MyDotCpp()沒有初始化?)
    wtw2162017-04-21 00:34 回復(fù)
    • 對(duì),因?yàn)樵谶M(jìn)入main之前沒有進(jìn)行內(nèi)存相關(guān)的初始化工作
      CTO2017-04-21 14:25 回復(fù)
  3. 看到了我不知道的東西,謝謝
    界道2018-03-14 19:18 回復(fù)
  4. 就喜歡這種文章,看完了更加深了自己對(duì)c語言一些原理的理解。謝謝樓主,希望加油!
    淺望2018-03-14 19:48 回復(fù)