青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Dict.CN 在線詞典, 英語學習, 在線翻譯

學??嘧髦?,書山勤為徑

留下點回憶

常用鏈接

統(tǒng)計

積分與排名

Denoise

English study

Web技術(shù)

數(shù)據(jù)壓縮

一些連接

最新評論

函數(shù)是如何被調(diào)用的?-探索代碼背后的故事

C/C++ 語言中,函數(shù)是如何被調(diào)用的呢?本文就實際的例子,走進匯編代碼來看下函數(shù)調(diào)用的過程。

首先看一個簡單的代碼例子:

void test(int i)

{

??? int j = i;

}

?

void test1()

{

?

}

?

int test2()

{

??? return 1;

}

?

void test3(int a,int b,int c)

{

}

?

void test4()

{

??? int i,j;

}

?

void test5()

{

??? int i,j,k,l;

}

?

int main()

{??

??? int i =0;

??? test1();

???

??? test(10);

???

??? test3(1,2,3);

?

??? i=test2();

???

??? test4();

???

??? test5();

?

??? return 0;

}

?

這段代碼很簡單, mian 函數(shù)調(diào)用幾個被測試的函數(shù),分別是:

1.? 沒有參數(shù)

2.? 有一個參數(shù)

3.? 3 個參數(shù)

4.? 有返回值

5.? 有兩個臨時變量

6.? 有多個臨時變量

?

VC7 中,我們將斷點設(shè)置到 main 函數(shù)入口的地方;然后 F5 運行程序。再按 ALT+8 反匯編,我們看到下面的代碼:

Main 函數(shù)變成這樣了:

int main()

{??

00401120? push??????? ebp?

00401121? mov???????? ebp,esp

00401123? sub???????? esp,0CCh

00401129? push??????? ebx?

0040112A ? push??????? esi?

0040112B? push??????? edi?

0040112C ? lea???????? edi,[ebp-0CCh]

00401132? mov???????? ecx,33h

00401137? mov?? ??????eax,0CCCCCCCCh

0040113C ? rep stos??? dword ptr [edi]

??? int i =0;

0040113E? mov???????? dword ptr [i],0 // 直接將數(shù)據(jù) 0 放到指定地址中

??? test1();

00401145? call??????? test1 (401030h)

???

??? test(10);

0040114A ? push??????? 0Ah?

0040114C ? call??????? test (401000h)

00401151? add???????? esp,4

???

??? test3(1,2,3);

00401154? push??????? 3???

00401156? push??????? 2???

00401158? push??????? 1???

0040115A ? call??????? test3 (401090h)

0040115F ? add???????? esp,0Ch

?

??? i=test2();

00401162? call??????? test2 (401060h)

00401167? mov???????? dword ptr [i],eax

?

??? test4();

0040116A ? call??????? test4 (4010C0h)

???

??? test5();

0040116F ? call ???????test5 (4010F0h)

?

??? return 0;

00401174? xor???????? eax,eax

}

00401176? pop???????? edi?

00401177? pop???????? esi?

00401178? pop???????? ebx?

00401179? add???????? esp,0CCh

0040117F ? cmp???????? ebp,esp

00401181? call??????? _RTC_CheckEsp (4011E0h)

00401186? mov???????? esp,ebp

00401188? pop???????? ebp?

00401189? ret?????????????

?

函數(shù)入口部分:

00401120? push??????? ebp? // 保存 ebp 的值

00401121? mov???????? ebp,esp // 將當前棧頂指針送到 ebp

00401123? sub???????? esp,0CCh // 將棧頂指針下移 0XCC 個字節(jié),為臨時變量留出空間

00401129? push??????? ebx? // 保存 ebx

0040112A ? push??????? esi? // 保存 esi

0040112B? push??????? edi? // 保存 edi

0040112C ? lea???????? edi,[ebp-0CCh] // edp-0CC 地址送 EAX

00401132? mov???????? ecx,33h //CC/4 得到的

00401137? mov???????? eax,0CCCCCCCCh // 初始化為 0XCCCCCCCCH

0040113C ? rep stos??? dword ptr [edi]// 復制

這寫匯編是編譯器為我們生成的函數(shù)入口部分,基本的含義是為臨時變量分配空間,并且初始化臨時變量。

這里需要說明幾點:

1.? 函數(shù)調(diào)用是通過堆棧來完成的。

2.? 函數(shù)入口的地方必須為臨時變量分配一定空間;實際上如果沒有臨時變量,也要留出 C0 個字節(jié)。

3.? 堆棧棧頂指針隨數(shù)據(jù)的進入逐漸減小。因此 sub esp , 0CCh 實際上是留出了 CC 個自己的堆??臻g。

我們看到實現(xiàn)將棧頂指針保存在 ebp 中,然后對該段空間設(shè)置初始值。而 0XCCCCCCH 是由堆棧的性質(zhì)決定,可以看 MSDN 。

如果開始的時候假設(shè) ESP 等于 0X12FEE0 ,那么在保存 EBP 之后, ESP 變成 0X12FEDC ,那么后來 EBP 中的值就是這個值,在保存的空間(從 0X12FE10 0X12FEDC )上將所有的內(nèi)存都初始化為 0XCC 。而 i 被分配在 0X12FED4 處,也就是第一個預(yù)留的位置)。

?

?

call??????? test1 (401030h)

由于已經(jīng)知道 i 的地址了,對 i 的賦值就很簡單了。這里看調(diào)用第一個沒有參數(shù)沒有返回值的 test1 函數(shù);僅僅一條語句,將 test1 的函數(shù)地址給 call 指令。

EAX = CCCCCCCC EBX = 7FFDE000 ECX = 00000000 EDX = 00000001

ESI = 00000040 EDI = 0012FEDC EIP = 00401145 ESP = 0012FE04

EBP = 0012FEDC EFL = 00000202

上面是 Call 指令調(diào)用前各寄存器的值;下面是調(diào)用后的值:

EAX = CCCCCCCC EBX = 7FFD7000 ECX = 00000000 EDX = 00000001

ESI = 00000040 EDI = 0012FEDC EIP = 00401030 ESP = 0012FE00

EBP = 0012FEDC EFL = 00000202

主要變化在于 EIP ESP ;前者是指令指針寄存器,而后者是堆棧指針寄存器。調(diào)用前指令的位置在 00401145 位置,而 call 指定將 EIP 改為 test1 的地址;同時將返回地址入棧;可以看到當前棧頂?shù)闹凳?/span> 0040114A ,實際上是 test1 的下條指令。

因此我們說 Call 指定做了兩件事情:

1.? EIP 從當前值改為被調(diào)用函數(shù)的值。

2.? 將返回地址,也就是當前地址的下條指令放入堆棧。

?

現(xiàn)在進入 test1 中看個究竟。

void test1()

{

00401030? push??????? ebp?

00401031? mov???????? ebp,esp

00401033? sub???????? esp,0C0h

00401039? push??????? ebx?

0040103A ? push??????? esi?

0040103B? push??????? edi?

0040103C ? lea???????? edi,[ebp-0C0h]

00401042? mov??? ?????ecx,30h

00401047? mov???????? eax,0CCCCCCCCh

0040104C ? rep stos??? dword ptr [edi]

?

}

0040104E? pop???????? edi?

0040104F ? pop???????? esi?

00401050? pop???????? ebx?

00401051? mov???????? esp,ebp

00401053? pop???????? ebp?

00401054? ret????? ??????

上面的命令基本相同,主要區(qū)別在于 test1 內(nèi)部沒有臨時變量,因此這里只保留了 C0 個自己的空間。

?

繼續(xù)回到主程序:

??? test(10);

0040114A ? push??????? 0Ah?

0040114C ? call??????? test (401000h)

00401151? add???????? esp,4

由于 test 函數(shù)有一個參數(shù),因此需要首先將參數(shù)壓入堆棧中,然后執(zhí)行與前面相似的操作。

這里有一點需要注意:函數(shù)返回之后需要將壓入的參數(shù)彈出;可以使用 pop 命令,也可以使用 add 命令來執(zhí)行。

?

對于 test3 的調(diào)用:

??? test3(1,2,3);

00401154? push??????? 3???

00401156? push??????? 2???

00401158? push??????? 1???

0040115A ? call??????? test3 (401090h)

0040115F ? add???????? esp,0Ch

?

由于它需要三個參數(shù),因此都必須壓入棧,返回的時候一次性彈出。

?

下面看如何調(diào)用帶有返回值的參數(shù):

??? i=test2();

00401162? call??????? test2 (401060h)

00401167? mov???????? dword ptr [i],eax

其他的相同,但重要的一點是函數(shù)的返回值是通過 eax 寄存器來返回的。

?

其他幾個函數(shù)的調(diào)用不同的是臨時變量數(shù)目的不同,僅僅在初始化預(yù)留空間的時候不同,基本上是每增加一個變量多出 12 個字節(jié)的堆??臻g。

?

mian 函數(shù)的返回值,有點特別:

??? return 0;

00401174? xor???????? eax,eax

特別的不在于通過 eax 返回,而是自己和自己異或,大部分返回 0 的函數(shù)都這么做。

?

mian 函數(shù)退出的時候有這段代碼:

00401176? pop???????? edi?

00401177? pop???????? esi?

00401178? pop???????? ebx?

00401179? add???????? esp,0CCh

0040117F ? cmp???????? ebp,esp

00401181? call??????? _RTC_CheckEsp (4011E0h)

00401186? mov???????? esp,ebp

00401188? pop???????? ebp?

00401189? ret?????????????

前面幾行是將寄存器的值恢復,而 add esp , 0CCh 是將保留的堆??臻g釋放,同時比較 ebp 是否與 esp 相等,如果不相等就提示相應(yīng)的錯誤,說明有內(nèi)存泄露等。最后將 ebp 彈出然后返回。

?

從上面的分析我們可以看到編譯器為我們做了很多事情,包括:堆??臻g分配和釋放、寄存器狀態(tài)保存、參數(shù)傳遞等。當然這些事情也可以完全由我們自己來完成,那么需要做的是使用關(guān)鍵字 naked 來聲明函數(shù)。

posted on 2007-01-18 15:08 笨笨 閱讀(2519) 評論(3)  編輯 收藏 引用 所屬分類: 編碼

評論

# re: 函數(shù)是如何被調(diào)用的?-探索代碼背后的故事 2007-01-18 15:09 笨笨

終于又找回密碼了,痛恨木馬編寫的人,痛恨病毒!同時感謝論壇斑竹的熱心幫助!  回復  更多評論   

# re: 函數(shù)是如何被調(diào)用的?-探索代碼背后的故事 2007-01-27 01:04 SonicLing

很多時候并不一定會用ebp來備份esp。包含ret的分支很少的函數(shù)用release編譯之后,直接會在ret之前將esp加回到原來的值,ebp用來干其他的事。

xor eax,eax是因為該指令比mov eax,0無論是在指令長度還是在執(zhí)行效率上都更優(yōu)秀。  回復  更多評論   

# re: 函數(shù)是如何被調(diào)用的?-探索代碼背后的故事 2007-01-29 08:45 笨笨

你說的很有道理,這里僅僅是將一段代碼再VC中反匯編的到的。當然,這里的代碼并非唯一的寫法。
所以,謝謝你的補充
  回復  更多評論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产国产亚洲一二三| 激情综合中文娱乐网| 国产精品www994| 国产精品videossex久久发布| 欧美国产日韩一区二区| 欧美黄污视频| 欧美日韩天堂| 国产精品美女黄网| 国产偷国产偷亚洲高清97cao| 国内成人在线| 亚洲高清不卡av| 亚洲精选在线观看| 亚洲一区二区少妇| 久久se精品一区精品二区| 久久香蕉国产线看观看网| 免费不卡中文字幕视频| 亚洲国产精选| 一级成人国产| 欧美一级理论片| 美女精品自拍一二三四| 欧美久久综合| 国产欧美精品一区aⅴ影院| 狠狠狠色丁香婷婷综合激情| 亚洲激情在线激情| 亚洲一区二区精品在线观看| 欧美主播一区二区三区美女 久久精品人| 久久九九精品| 亚洲国产日韩综合一区| 中文日韩欧美| 久久免费视频网站| 欧美日韩国产成人精品| 国产一区二区三区在线播放免费观看 | 男女视频一区二区| 亚洲精品一区在线| 欧美亚洲免费电影| 欧美国产三区| 国产日韩精品视频一区| 91久久久亚洲精品| 性欧美1819sex性高清| 欧美刺激性大交免费视频| 日韩视频一区二区在线观看 | 欧美日韩视频在线| 国产一区二区日韩| 一区二区三区国产| 久久综合狠狠综合久久综合88| 亚洲精选大片| 久久精品国产亚洲5555| 欧美日韩在线一区二区| 在线观看亚洲a| 午夜欧美大片免费观看| 欧美韩国日本一区| 午夜精品国产| 欧美日韩一区二区三区免费看| 精品成人国产在线观看男人呻吟| 中国成人黄色视屏| 欧美电影专区| 午夜精品区一区二区三| 欧美日韩国产首页| 亚洲高清视频中文字幕| 欧美伊人久久大香线蕉综合69| 亚洲国产第一| 久久久av网站| 国产日韩在线视频| 亚洲免费视频网站| 亚洲国产精品欧美一二99| 久久激情久久| 国产日韩欧美精品在线| 亚洲淫性视频| 亚洲日本激情| 美国十次成人| 伊人夜夜躁av伊人久久| 欧美在线视频在线播放完整版免费观看 | 这里只有精品视频| 欧美激情一区二区久久久| 久久精品国产亚洲高清剧情介绍| 国产精品欧美一区喷水 | 亚洲国产一区二区三区青草影视| 久久精品国亚洲| 亚洲欧美日韩一区在线| 国产精品久久91| 亚洲一级电影| 一级成人国产| 欧美日韩成人在线观看| 亚洲精品视频免费在线观看| 欧美激情五月| 免费不卡在线视频| 亚洲狠狠婷婷| 欧美激情视频一区二区三区免费| 久久久久久自在自线| 国内久久视频| 久久综合九色综合久99| 久久9热精品视频| 好看不卡的中文字幕| 久久露脸国产精品| 久久久国产精品一区| 精品不卡在线| 欧美a级片一区| 免费成人毛片| 日韩视频在线你懂得| 亚洲精品免费在线| 欧美日韩mv| 亚洲天堂免费观看| 亚洲婷婷在线| 国产欧美一区二区三区另类精品| 久久精品成人| 久久久免费av| 亚洲日韩欧美视频| 亚洲精品中文字幕在线| 国产精品白丝jk黑袜喷水| 亚洲午夜视频在线| 亚洲女人天堂成人av在线| 国产日韩视频一区二区三区| 久久阴道视频| 欧美成人久久| 亚洲午夜视频在线观看| 亚洲欧美精品一区| 黄色成人在线| 亚洲国产网站| 国产精品久久二区| 久久精品欧美| 美女诱惑一区| 亚洲一区二区高清视频| 午夜精品婷婷| 亚洲黄色天堂| 一本色道88久久加勒比精品| 国产人久久人人人人爽| 免费成人你懂的| 欧美日韩精品伦理作品在线免费观看| 亚洲欧美久久久久一区二区三区| 欧美一区二区三区在线看| 亚洲二区视频| 一级成人国产| 国内揄拍国内精品久久| 亚洲国产精品一区二区久| 国产精品久久久久久久久搜平片| 久久久av毛片精品| 欧美精品国产精品日韩精品| 欧美一级片久久久久久久| 久久九九免费| 亚洲午夜久久久久久尤物| 欧美在线视频播放| 99国产精品久久久久久久| 西瓜成人精品人成网站| 亚洲精品美女在线| 午夜精品久久久久影视| 亚洲国产一区二区精品专区| 亚洲一区二区三区色| 亚洲高清资源综合久久精品| 这里只有精品电影| 亚洲经典视频在线观看| 亚洲一区二区免费视频| 亚洲日韩中文字幕在线播放| 亚洲欧美日韩另类| 99视频+国产日韩欧美| 欧美在线视频观看| 亚洲视频自拍偷拍| 另类亚洲自拍| 欧美在线一级va免费观看| 欧美激情在线狂野欧美精品| 久久精品一区二区| 欧美视频日韩视频在线观看| 免费视频一区| 国产欧美日韩三级| 日韩一区二区电影网| 亚洲国产日韩欧美| 欧美与黑人午夜性猛交久久久| 亚洲视频中文| 欧美国产日韩xxxxx| 毛片av中文字幕一区二区| 国产精品网站在线播放| 亚洲精品欧美一区二区三区| 在线精品在线| 欧美一区亚洲| 午夜在线精品偷拍| 欧美日韩在线直播| 亚洲国产精品尤物yw在线观看| 狠狠色综合网站久久久久久久| 亚洲一区在线免费观看| 亚洲视频一区二区免费在线观看| 麻豆乱码国产一区二区三区| 久久久噜噜噜久久久| 国产精品入口夜色视频大尺度| 亚洲精品一区中文| 亚洲精品日产精品乱码不卡| 久久婷婷麻豆| 麻豆精品91| 国产综合自拍| 欧美制服丝袜| 久久久国产亚洲精品| 国产日韩1区| 亚洲欧美区自拍先锋| 午夜天堂精品久久久久| 国产精品盗摄久久久| 在线视频精品| 亚洲免费在线观看视频| 国产精品扒开腿爽爽爽视频| 一本色道久久综合亚洲91| 亚洲私人影吧| 欧美午夜精品电影| 亚洲午夜精品一区二区|