X86匯編語言學(xué)習(xí)_第1頁
X86匯編語言學(xué)習(xí)_第2頁
X86匯編語言學(xué)習(xí)_第3頁
X86匯編語言學(xué)習(xí)_第4頁
X86匯編語言學(xué)習(xí)_第5頁
已閱讀5頁,還剩11頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、X86匯編語言學(xué)習(xí)手記X86匯編語言學(xué)習(xí)手記(1)1. 編編譯環(huán)境境 OOS: Sollariis 99 X886 CComppileer: gccc 3.3.22 Liinkeer: Sollariis LLinkk Edditoors 5.xx Deebugg Toool: mddb EEdittor: vii 注注:關(guān)于于編譯環(huán)環(huán)境的安安裝和設(shè)設(shè)置,可可以參考考文章:Sollariis 上上的開發(fā)發(fā)環(huán)境安安裝及設(shè)設(shè)置。 mddb是SSolaariss提供的的kerrnell deebugg工具,這里用用它做反反匯編和和匯編語語言調(diào)試試工具。 如如果在LLinuux平臺(tái)臺(tái)可以用用gdbb進(jìn)

2、行反反匯編和和調(diào)試。 2. 最最簡C代代碼分析析 為簡化化問題,來分析析一下最最簡的cc代碼生生成的匯匯編代碼碼: # vvi ttestt1.cc intt maain() reeturrn 00; 編編譯該程程序,產(chǎn)產(chǎn)生二進(jìn)進(jìn)制文件件: # ggcc tesst1.c -o ttestt1 # ffilee teest11 teest11: EELF 32-bitt LSSB eexeccutaablee 8003866 Veersiion 1, dynnamiicallly linnkedd, nnot strrippped tesst1是是一個(gè)EELF格格式322位小端端(Liittl

3、le EEndiian)的可執(zhí)執(zhí)行文件件,動(dòng)態(tài)態(tài)鏈接并并且符號(hào)號(hào)表沒有有去除。 這這正是UUnixx/Liinuxx平臺(tái)典典型的可可執(zhí)行文文件格式式。 用mddb反匯匯編可以以觀察生生成的匯匯編代碼碼: # mmdb tesst1 Looadiing moddulees: llibcc.soo.1 mmainn:ddis ; 反匯編編maiin函數(shù)數(shù),mddb的命命令一般般格式為為 :ddis maain: puushll %ebbp ; ebbp寄存存器內(nèi)容容壓棧,即保存存maiin函數(shù)數(shù)的上級(jí)級(jí)調(diào)用函函數(shù)的棧棧基地址址 mmainn+1: mmovll %eesp,%ebbp ; eesp

4、值值賦給eebp,設(shè)置mmainn函數(shù)的的?;分?mmainn+3: suubl $8,%essp maiin+66: aandll $00 xf00,%eesp maain+9: movvl $0,%eaxx mmainn+0 xxe: suubl %eaax,%espp mmainn+0 xx10: mmovll $00,%eeax ; 設(shè)設(shè)置函數(shù)數(shù)返回值值0 maiin+00 x155: leaave ; 將ebbp值賦賦給essp,ppop先先前棧內(nèi)內(nèi)的上級(jí)級(jí)函數(shù)棧棧的基地地址給eebp,恢復(fù)原原?;分?mmainn+0 xx16: rret ; mmainn函數(shù)返返回,回回到上級(jí)

5、級(jí)調(diào)用 注:這這里得到到的匯編編語言語語法格式式與Inntell的手冊(cè)冊(cè)有很大大不同,Uniix/LLinuux采用用AT&T匯編編格式作作為匯編編語言的的語法格格式 如如果想了了解ATT&T匯匯編可以以參考文文章:LLinuux AAT&TT 匯編編語言開開發(fā)指南南 問題:誰調(diào)用用了 mmainn函數(shù)? 在C語語言的層層面來看看,maain函函數(shù)是一一個(gè)程序序的起始始入口點(diǎn)點(diǎn),而實(shí)實(shí)際上,ELFF可執(zhí)行行文件的的入口點(diǎn)點(diǎn)并不是是maiin而是是_sttartt。 mddb也可可以反匯匯編_sstarrt: _staart:diis ;從_staart 的地址址開始反反匯編 _sstarrt:

6、 puushll $0 _sstarrt+22: puushll $0 _sstarrt+44: moovl %essp,%ebpp _staart+6: ppushhl %eedx _sstarrt+77: moovl $0 xx805504bb0,%eaxx _staart+0 xcc: ttesttl %eeax,%eaax _sttartt+0 xxe: je +0 xff _sttartt+0 xx10: pusshl $0 x8805004b00 _staart+0 x115: ccalll -00 x755 _sttartt+0 xx1a: adddl $4,%espp _sta

7、art+0 x11d: mmovll $00 x800607710,%eaax _sttartt+0 xx22: tesstl %eaxx,%eeax _sstarrt+00 x244: jee +7 _sstarrt+00 x266: caall -0 xx86 _staart+0 x22b: ppushhl $00 x8005066cd _sstarrt+00 x300: caall -0 xx90 _staart+0 x335: mmovll +88(%eebp),%eeax _sstarrt+00 x388: leeal +0 xx10(%ebbp,%eaxx,4),%eedx _ss

8、tarrt+00 x3cc: moovl %eddx,00 x800608804 _sstarrt+00 x422: anndl $0 xxf0,%essp _sttartt+0 xx45: subbl $4,%espp _staart+0 x448: ppushhl %eedx _sstarrt+00 x499: leeal +0 xxc(%ebpp),%edxx _staart+0 x44c: ppushhl %eedx _sstarrt+00 x4dd: puushll %eaax _sttartt+0 xx4e: calll +0 x1152 _sttartt+0 xx53: call

9、l -0 xaa3 _sstarrt+00 x588: calll +0 xffb ;在這里里調(diào)用了了maiin函數(shù)數(shù) _staart+0 x55d: aaddll $00 xc,%essp _sttartt+0 xx60: pusshl %eaxx _staart+0 x661: ccalll -00 xa11 _sstarrt+00 x666: puushll $0 _sstarrt+00 x688: moovl $1,%eaax _sttartt+0 xx6d: lcaall $7,$0 _sttartt+0 xx74: hltt 問題:為什么么用EAAX寄存存器保存存函數(shù)返返回值? 實(shí)

10、實(shí)際上IIA322并沒有有規(guī)定用用哪個(gè)寄寄存器來來保存返返回值。但如果果反匯編編Sollariis/LLinuux的二二進(jìn)制文文件,就就會(huì)發(fā)現(xiàn)現(xiàn),都用用EAXX保存函函數(shù)返回回值。 這不不是偶然然現(xiàn)象,是操作作系統(tǒng)的的ABII(Apppliicattionn Biinarry IInteerfaace)來決定定的。 Soolarris/Linnux操操作系統(tǒng)統(tǒng)的ABBI就是是Syttem V AABI。 概念:SFPP (SStacck FFramme PPoinnterr) 棧??蚣苤钢羔?正確理理解SFFP必須須了解: IA332 的的棧的概概念 CPPU 中中32位位寄存器器ESPP/E

11、BBP的作作用 PUUSH/POPP 指令令是如何何影響棧棧的 CAALL/RETT/LEEAVEE 等指指令是如如何影響響棧的 如我們們所知: 11)IAA32的的棧是用用來存放放臨時(shí)數(shù)數(shù)據(jù),而而且是LLIFOO,即后后進(jìn)先出出的。棧棧的增長長方向是是從高地地址向低低地址增增長,按按字節(jié)為為單位編編址。 2) EBBP是棧?;返牡闹羔?,永遠(yuǎn)指指向棧底底(高地地址),ESPP是棧指指針,永永遠(yuǎn)指向向棧頂(低地址址)。 3) PUUSH一一個(gè)loong型型數(shù)據(jù)時(shí)時(shí),以字字節(jié)為單單位將數(shù)數(shù)據(jù)壓入入棧,從從高到低低按字節(jié)節(jié)依次將將數(shù)據(jù)存存入ESSP-11、ESSP-22、ESSP-33、ESSP-

12、44的地址址單元。 44) PPOP一一個(gè)loong型型數(shù)據(jù),過程與與PUSSH相反反,依次次將ESSP-44、ESSP-33、ESSP-22、ESSP-11從棧內(nèi)內(nèi)彈出,放入一一個(gè)322位寄存存器。 5) CAALL指指令用來來調(diào)用一一個(gè)函數(shù)數(shù)或過程程,此時(shí)時(shí),下一一條指令令地址會(huì)會(huì)被壓入入堆棧,以備返返回時(shí)能能恢復(fù)執(zhí)執(zhí)行下條條指令。 66) RRET指指令用來來從一個(gè)個(gè)函數(shù)或或過程返返回,之之前CAALL保保存的下下條指令令地址會(huì)會(huì)從棧內(nèi)內(nèi)彈出到到EIPP寄存器器中,程程序轉(zhuǎn)到到CALLL之前前下條指指令處執(zhí)執(zhí)行 7) ENTTER是是建立當(dāng)當(dāng)前函數(shù)數(shù)的??蚩蚣?,即即相當(dāng)于于以下兩兩條指令

13、令: puushll %ebbp moovl %essp,%ebpp 88) LLEAVVE是釋釋放當(dāng)前前函數(shù)或或者過程程的??蚩蚣?,即即相當(dāng)于于以下兩兩條指令令: moovl ebpp essp poopl ebbp 如果反反匯編一一個(gè)函數(shù)數(shù),很多多時(shí)候會(huì)會(huì)在函數(shù)數(shù)進(jìn)入和和返回處處,發(fā)現(xiàn)現(xiàn)有類似似如下形形式的匯匯編語句句: ppushhl %eebp ; ebbp寄存存器內(nèi)容容壓棧,即保存存maiin函數(shù)數(shù)的上級(jí)級(jí)調(diào)用函函數(shù)的棧?;刂分?movvl %espp,%eebp ; eesp值值賦給eebp,設(shè)置 maiin函數(shù)數(shù)的?;?. ; 以上兩兩條指令令相當(dāng)于于 ennterr 0,

14、0 . leaave ; 將將ebpp值賦給給espp,poop先前前棧內(nèi)的的上級(jí)函函數(shù)棧的的基地址址給ebbp,恢恢復(fù)原棧?;?rret ; maain函函數(shù)返回回,回到到上級(jí)調(diào)調(diào)用 這些語語句就是是用來創(chuàng)創(chuàng)建和釋釋放一個(gè)個(gè)函數(shù)或或者過程程的??蚩蚣艿摹?原原來編譯譯器會(huì)自自動(dòng)在函函數(shù)入口口和出口口處插入入創(chuàng)建和和釋放棧??蚣艿牡恼Z句。 函函數(shù)被調(diào)調(diào)用時(shí): 11) EEIP/EBPP成為新新函數(shù)棧棧的邊界界 函函數(shù)被調(diào)調(diào)用時(shí),返回時(shí)時(shí)的EIIP首先先被壓入入堆棧;創(chuàng)建棧??蚣軙r(shí)時(shí),上級(jí)級(jí)函數(shù)棧棧的EBBP被壓壓入堆棧棧,與EEIP一一道行成成新函數(shù)數(shù)棧框架架的邊界界 22) EEBP成成為

15、棧框框架指針針SFPP,用來來指示新新函數(shù)棧棧的邊界界 棧??蚣芙ń⒑?,EBPP指向的的棧的內(nèi)內(nèi)容就是是上一級(jí)級(jí)函數(shù)棧棧的EBBP,可可以想象象,通過過EBPP就可以以把層層層調(diào)用函函數(shù)的棧棧都回朔朔遍歷一一遍,調(diào)調(diào)試器就就是利用用這個(gè)特特性實(shí)現(xiàn)現(xiàn) baackttracce功能能的 3) ESPP總是作作為棧指指針指向向棧頂,用來分分配??湛臻g 棧分配配空間給給函數(shù)局局部變量量時(shí)的語語句通常常就是給給ESPP減去一一個(gè)常數(shù)數(shù)值,例例如,分分配一個(gè)個(gè)整型數(shù)數(shù)據(jù)就是是 ESSP-44 44) 函函數(shù)的參參數(shù)傳遞遞和局部部變量訪訪問可以以通過SSFP即即EBPP來實(shí)現(xiàn)現(xiàn) 由于棧??蚣苤钢羔樣肋h(yuǎn)遠(yuǎn)指

16、向當(dāng)當(dāng)前函數(shù)數(shù)的?;刂?,參數(shù)和和局部變變量訪問問通常為為如下形形式: +8+xxx(%ebpp) ; 函數(shù)入入口參數(shù)數(shù)的的訪訪問 -xxx(%ebpp) ; 函函數(shù)局部部變量訪訪問 假如如函數(shù)AA調(diào)用函函數(shù)B,函數(shù)BB調(diào)用函函數(shù)C ,則函函數(shù)??蚩蚣芗罢{(diào)調(diào)用關(guān)系系如下圖圖所示: b:77711101bbbb00下圖圖有點(diǎn)亂亂,因此此刪去部部分內(nèi)容容,要看看原圖可可參考我我的bllog/b:77111011bbbb0 +-+- 高地址址 | EIPP (上上級(jí)函數(shù)數(shù)返回地地址) | +-+ | EBPP (上上級(jí)函數(shù)數(shù)的EBBP) | +-+ | Loocall Vaariaablees |

17、 | . | +-+ | AArg n(函函數(shù)B的的第n個(gè)個(gè)參數(shù)) | +-+ | Argg .(函數(shù)BB的第.個(gè)參數(shù)數(shù)) | +-+ | Argg 1(函數(shù)BB的第11個(gè)參數(shù)數(shù)) | +-+ | AArg 0(函函數(shù)B的的第0個(gè)個(gè)參數(shù)) | +-+ EEIP (A函函數(shù)的返返回地址址) | +-+ | EEBP (A函函數(shù)的EEBP) | +-+ | Loccal Varriabbless | | . | +-+ | Argg n(函數(shù)CC的第nn個(gè)參數(shù)數(shù)) | +-+ | Arrg .(函數(shù)數(shù)C的第第.個(gè)參參數(shù)) | +-+ | Argg 1(函數(shù)CC的第11個(gè)參數(shù)數(shù)) | +-+ | A

18、Arg 0(函函數(shù)C的的第0個(gè)個(gè)參數(shù)) | +-+ | EIPP (BB函數(shù)的的返回地地址) | +-+ | EBPP (BB函數(shù)的的EBPP) | +-+ | Loccal Varriabbless | | . | +-+- 低地址址 圖圖 1-1 再分析析tesst1反反匯編結(jié)結(jié)果中剩剩余部分分語句的的含義: # mddb ttestt1 Loaadinng mmoduuless: liibc.so.1 maain:diis ; 反匯編編maiin函數(shù)數(shù) mmainn: ppushhl %eebp mmainn+1: mmovll %eesp,%ebbp ; 創(chuàng)創(chuàng)建Sttackk Frra

19、mee(棧框框架) maain+3: subbl $8,%espp ; 通過EESP-8來分分配8字字節(jié)堆棧??臻g maain+6: anddl $0 xff0,%espp ; 使棧地地址166字節(jié)對(duì)對(duì)齊 maiin+99: mmovll $00,%eeax ; 無無意義 maain+0 xee: subbl %eaxx,%eesp ; 無意義義 mmainn+0 xx10: mmovll $00,%eeax ; 設(shè)設(shè)置maain函函數(shù)返回回值 maiin+00 x155: leaave ; 撤銷SStacck FFramme(棧棧框架) mmainn+0 xx16: rret ; mmain

20、n 函數(shù)數(shù)返回 以下兩兩句似乎乎是沒有有意義的的,果真真是這樣樣嗎? mmovll $00,%eeax subbl %eaax,%espp 用ggcc的的O2級(jí)級(jí)優(yōu)化來來重新編編譯teest11.c: # gccc -O2 tesst1.c -o ttestt1 # mmdb tesst1 maiin:diss mmainn: puushll %ebbp maiin+11: mmovll %eesp,%ebbp maiin+33: ssubll $88,%eesp maain+6: anddl $0 xff0,%espp mmainn+9: xoorl %eaax,%eaxx ; 設(shè)設(shè)置maa

21、in返返回值,使用xxorll異或指指令來使使eaxx為0 maain+0 xbb: leaave maain+0 xcc: rett 新的反反匯編結(jié)結(jié)果比最最初的結(jié)結(jié)果要簡簡潔一些些,果然然之前被被認(rèn)為無無用的語語句被優(yōu)優(yōu)化掉了了,進(jìn)一一步驗(yàn)證證了之前前的猜測測。 提示:編譯器器產(chǎn)生的的某些語語句可能能在程序序?qū)嶋H語語義上沒沒有用處處,可以以用優(yōu)化化選項(xiàng)去去掉這些些語句。 問題:為什么么用xoorl來來設(shè)置eeax的的值? 注意意到優(yōu)化化后的代代碼中,eaxx返回值值的設(shè)置置由 mmovll $00,%eeax 變?yōu)?xorrl %eaxx,%eeax ,這是是因?yàn)镮IA322指令中中,xo

22、orl比比movvl有更更高的運(yùn)運(yùn)行速度度。 概念:Staack aliigneed 棧棧對(duì)齊 那么么,以下下語句到到底是和和作用呢呢? suubl $8,%essp anddl $0 xff0,%espp ; 通過過anddl使低低4位為為0,保保證棧地地址166字節(jié)對(duì)對(duì)齊 表表面來看看,這條條語句最最直接的的后果是是使ESSP的地地址后44位為00,即116字節(jié)節(jié)對(duì)齊,那么為為什么這這么做呢呢? 原來,IA332 系系列CPPU的一一些指令令分別在在4、88、166字節(jié)對(duì)對(duì)齊時(shí)會(huì)會(huì)有更快快的運(yùn)行行速度,因此ggcc編編譯器為為提高生生成代碼碼在IAA32上上的運(yùn)行行速度,默認(rèn)對(duì)對(duì)產(chǎn)生的的代

23、碼進(jìn)進(jìn)行166字節(jié)對(duì)對(duì)齊 anndl $0 xxf0,%essp 的的意義很很明顯,那么 subbl $8,%espp 呢,是必須須的嗎? 這這里假設(shè)設(shè)在進(jìn)入入maiin函數(shù)數(shù)之前,棧是116字節(jié)節(jié)對(duì)齊的的話,那那么,進(jìn)進(jìn)入maain函函數(shù)后,EIPP和EBBP被壓壓入堆棧棧后,棧棧地址最最末4位位二進(jìn)制制位必定定是 110000,essp -8則恰恰好使后后4位地地址二進(jìn)進(jìn)制位為為00000。看看來,這這也是為為保證棧棧16字字節(jié)對(duì)齊齊的。 如果查查一下ggcc的的手冊(cè),就會(huì)發(fā)發(fā)現(xiàn)關(guān)于于棧對(duì)齊齊的參數(shù)數(shù)設(shè)置: -mprrefeerreed-sstacck-bbounndarry=nn ; 希

24、望棧棧按照22的n次次的字節(jié)節(jié)邊界對(duì)對(duì)齊, n的取取值范圍圍是2-12 默認(rèn)情情況下,n是等等于4的的,也就就是說,默認(rèn)情情況下,gccc是166字節(jié)對(duì)對(duì)齊,以以適應(yīng)IIA322大多數(shù)數(shù)指令的的要求。 讓我們們利用-mprrefeerreed-sstacck-bbounndarry=22來去除除棧對(duì)齊齊指令: # ggcc -mpprefferrred-staack-bouundaary=2 ttestt1.cc -oo teest11 maiin:diss mmainn: ppushhl %eebp maain+1: moovl %essp,%ebpp mmainn+3: mmovll $0

25、0,%eeax maain+8: leeavee mmainn+9: rret 可以看看到,棧棧對(duì)齊指指令沒有有了,因因?yàn)?,IIA322的棧本本身就是是4字節(jié)節(jié)對(duì)齊的的,不需需要用額額外指令令進(jìn)行對(duì)對(duì)齊。 那么么,??蚩蚣苤羔樶楽FPP是不是是必須的的呢? # gccc -mmpreeferrredd-sttackk-boounddaryy=2 -foomitt-frramee-poointter tesst1.c -o ttestt maiin:diss mmainn: mmovll $00,%eeax maain+5: reet 由此可可知,-fommit-fraame-poiinteer

26、 可可以去除除SFPP。 問問題:去去除SFFP后有有什么缺缺點(diǎn)呢? 1)增加調(diào)調(diào)式難度度 由于SSFP在在調(diào)試器器baccktrracee的指令令中被使使用到,因此沒沒有SFFP該調(diào)調(diào)試指令令就無法法使用。 22)降低低匯編代代碼可讀讀性 函數(shù)數(shù)參數(shù)和和局部變變量的訪訪問,在在沒有eebp的的情況下下,都只只能通過過+xxx(essp)的的方式訪訪問,而而很難區(qū)區(qū)分兩種種方式,降低了了程序的的可讀性性。 問問題:去去除SFFP有什什么優(yōu)點(diǎn)點(diǎn)呢? 1)節(jié)節(jié)省??湛臻g 2)減減少建立立和撤銷銷??蚣芗艿闹噶盍詈?,簡簡化了代代碼 3)使使ebpp空閑出出來,使使之作為為通用寄寄存器使使用,增增加通

27、用用寄存器器的數(shù)量量 44)以上上3點(diǎn)使使得程序序運(yùn)行速速度更快快 概念:Calllinng CConvventtionn 調(diào)調(diào)用約定定和 AABI (Apppliicattionn Biinarry IInteerfaace) 應(yīng)用用程序二二進(jìn)制接接口 函函數(shù)如何何找到它它的參數(shù)數(shù)? 函數(shù)數(shù)如何返返回結(jié)果果? 函數(shù)數(shù)在哪里里存放局局部變量量? 那一一個(gè)硬件件寄存器器是起始始空間? 那一個(gè)個(gè)硬件寄寄存器必必須預(yù)先先保留? Calllinng CConvventtionn 調(diào)調(diào)用約定定對(duì)以上上問題作作出了規(guī)規(guī)定。CCalllingg Coonveentiion也也是ABBI的一一部分。 因因此,

28、遵遵守相同同ABII規(guī)范的的操作系系統(tǒng),使使其相互互間實(shí)現(xiàn)現(xiàn)二進(jìn)制制代碼的的互操作作成為了了可能。 例例如:由由于Soolarris、Linnux都都遵守SSysttem V的AABI,Sollariis 110就提提供了直直接運(yùn)行行Linnux二二進(jìn)制程程序的功功能。 詳見見文章:關(guān)注: Soolarris 10的的10大大新變化化 3. 小結(jié)結(jié) 本本文通過過最簡的的C程序序,引入入以下概概念: SSFP ??蚣芗苤羔?SStacck aaliggnedd 棧對(duì)對(duì)齊 Caalliing Connvenntioon 調(diào)用約約定 和和 ABBI (Apppliccatiion Binnaryy

29、Innterrfacce) 應(yīng)用程程序二進(jìn)進(jìn)制接口口 今今后,將將通過進(jìn)進(jìn)一步的的實(shí)驗(yàn),來深入入了解這這些概念念。通過過掌握這這些概念念,使在在匯編級(jí)級(jí)調(diào)試程程序產(chǎn)生生的coore dummp、掌掌握C語語言高級(jí)級(jí)調(diào)試技技巧成為為了可能能。X86匯匯編語言言學(xué)習(xí)手手記(22)這是作者者在學(xué)習(xí)習(xí)X866匯編過過程中的的學(xué)習(xí)筆筆記,難難免有錯(cuò)錯(cuò)誤和疏疏漏之處處,歡迎迎指正。作者將將隨時(shí)修修改錯(cuò)誤誤并將新新的版本本發(fā)布在在自己的的Bloog站點(diǎn)點(diǎn)上。嚴(yán)嚴(yán)格說來來,本篇篇文檔更更側(cè)重于于C語言言和C編編譯器方方面的知知識(shí),如如果涉及及到基本本的匯編編語言的的內(nèi)容,可以參參考相關(guān)關(guān)文檔。 自XX86 匯

30、編語語言學(xué)習(xí)習(xí)手記(1)在在作者的的Bloog上發(fā)發(fā)布以來來,得到到了很多多網(wǎng)友的的肯定和和鼓勵(lì),并且還還有熱心心網(wǎng)友指指出了其其中的錯(cuò)錯(cuò)誤,b:bbea666dddae00作者者已經(jīng)將將文檔中中已發(fā)現(xiàn)現(xiàn)的錯(cuò)誤誤修正后后更新在在Bloog上。/bb:beea666ddaae0 上一篇篇文章通通過分析析一個(gè)最最簡的CC程序,引出了了以下概概念: SStacck FFramme 棧??蚣?和 SSFP ??蚣芗苤羔?SStacck aaliggnedd 棧對(duì)對(duì)齊 Caalliing Connvenntioon 調(diào)用約約定 和和 ABBI (Apppliccatiion Binnaryy Innte

31、rrfacce) 應(yīng)用程程序二進(jìn)進(jìn)制接口口 本本章中,將通過過進(jìn)一步步的實(shí)驗(yàn)驗(yàn),來深深入了解解這些概概念。如如果還不不了解這這些概念念,可以以參考 X866匯編語語言學(xué)習(xí)習(xí)手記(1)。 1. 局部部變量的的棧分配配 上篇文文章已經(jīng)經(jīng)分析過過一個(gè)最最簡的CC程序, 下下面我們們分析一一下C編編譯器如如何處理理局部變變量的分分配,為為此先給給出如下下程序: #vii teest22.c intt maain() innt ii; innt jj=2; i=33; i=+ii; reeturrn ii+j; 編譯該該程序,產(chǎn)生二二進(jìn)制文文件,并并利用mmdb來來觀察程程序運(yùn)行行中的sstacck的狀

32、狀態(tài): #ggcc tesst2.c -o ttestt2 #mddb ttestt2 Loaadinng mmoduuless: liibc.so.1 maain:diis maiin: puushll %ebbp maiin+11: moovl %essp,%ebpp ; maiin至mmainn+1,創(chuàng)建SStacck FFramme maiin+33: suubl $8,%essp ; 為局部部變量ii,j分分配??湛臻g,并并保證棧棧16字字節(jié)對(duì)齊齊 mmainn+6: anddl $0 xff0,%espp mmainn+9: movvl $0,%eaxx mmainn+0 xxe:

33、 subbl %eaxx,%eesp ; mmainn+6至至maiin+00 xe,再次保保證棧116字節(jié)節(jié)對(duì)齊 mmainn+0 xx10: movvl $2,-8(%ebpp) ; 初初始化局局部變量量j的值值為2 maain+0 x117: mmovll $33,-44(%eebp) ; 給局局部變量量i賦值值為3 maain+0 x11e: lleall -44(%eebp),%eeax ; 將局局部變量量i的地地址裝入入到EAAX寄存存器中 maain+0 x221: iincll (%eaxx) ; i+ maiin+00 x233: moovl -8(%ebbp),%eaax

34、; 將j的的值裝入入EAXX mmainn+0 xx26: adddl -4(%ebpp),%eaxx ; ii+j并并將結(jié)果果存入EEAX,作為返返回值 maain+0 x229: lleavve ; 撤撤銷Sttackk Frramee maiin+00 x2aa: reet ; maain函函數(shù)返回回 mmainn+0 xx10:b ; 在地址址 maain+0 x110處設(shè)設(shè)置斷點(diǎn)點(diǎn) maain+0 x11e:bb ; 在在maiin+00 x1ee設(shè)置斷斷點(diǎn) mmainn+0 xx29:b ; 在maain+0 x11e設(shè)置置斷點(diǎn) maiin+00 x2aa:b ; 在mmainn+

35、0 xx1e設(shè)設(shè)置斷點(diǎn)點(diǎn) 下下面的mmdb的的4個(gè)命命令在一一行輸入入,中間間用分號(hào)號(hào)間隔開開,命令令的含義義在注釋釋中給出出: :r;espp,100/naap;ebpp=X;eaax=XX ; 運(yùn)行程程序(:r 命命令) mddb: stoop aat mmainn+0 xx10 ; 以EESP寄寄存器為為起始地地址,指指定格式式輸出116字節(jié)節(jié)的棧內(nèi)內(nèi)容(espp,100/naap 命命令) mddb: tarrgett sttoppped at: ; 在最后后輸出EEBP和和EAXX寄存器器的值(ebbp=XX 命令令 和 :c;espp,100/naap;ebpp=X; :cc;ee

36、sp,10/napp;eebp=X; :cc;eesp,10/napp;eebp=X; :s;espp,100/naap;ebpp=X; 通過mmdb對(duì)對(duì)程序運(yùn)運(yùn)行時(shí)的的寄存器器和棧的的觀察和和分析,可以得得出局部部變量在在棧中的的訪問和和分配及及釋放方方式: 11.局部部變量的的分配,可以通通過essp減去去所需字字節(jié)數(shù) subbl $8,%espp 2.局局部變量量的釋放放,可以以通過lleavve指令令 lleavve 33.局部部變量的的訪問,可以通通過ebbp減去去偏移量量 moovl -8(%ebbp),%eaax aaddll -44(%eebp),%eeax 問題:當(dāng)存在在2個(gè)

37、以以上的局局部變量量時(shí),如如何進(jìn)行行棧對(duì)齊齊? 在上篇篇文章中中,提到到subbl $8,%espp語句除除了分配配??臻g間外,還還有一個(gè)個(gè)作用就就是棧對(duì)對(duì)齊。那那么本例例中,由由于i和和j正好好是8字字節(jié),那那么如果果存在22個(gè)以上上的局部部變量時(shí)時(shí),如何何同時(shí)滿滿足空間間分配和和棧對(duì)齊齊呢? 2. 兩兩個(gè)以上上的局部部變量的的棧分配配 在之前前的C程程序中,增加局局部變量量定義kk,程序序如下: # vii teest33.c intt maain() innt ii, jj=2, k=4; ii=3; i=+i; k=ii+j+k; rretuurn k; 編譯該該程序后后,用mmdb反

38、反匯編得得出如下下結(jié)果: # gccc ttestt3.cc -oo teest33 # mmdb tesst3 Looadiing moddulees: llibcc.soo.1 mmainn:ddis maain: pusshl %ebpp mmainn+1: moovl %essp,%ebpp ; mmainn至maain+1,創(chuàng)創(chuàng)建Sttackk Frramee mmainn+3: subbl $00 x188,%eesp ; 為局局部變量量i,jj,k分分配??湛臻g,并并保證棧棧16字字節(jié)對(duì)齊齊 mmainn+6: anndl $0 xxf0,%essp maiin+99: mmov

39、ll $00,%eeax maain+0 xee: subbl %eaxx,%eesp ; maain+6至mmainn+0 xxe,再再次保證證棧166字節(jié)對(duì)對(duì)齊 maiin+00 x100: mmovll $22,-88(%eebp) ; j=22 mmainn+0 xx17: moovl $4,-0 xxc(%ebpp) ; kk=4 maain+0 x11e: movvl $3,-4(%ebpp) ; i=3 maiin+00 x255: lleall -44(%eebp),%eeax ; 將i的的地址裝裝入到EEAX maain+0 x228: inccl (%eaax) ; i+

40、maiin+00 x2aa: mmovll -88(%eebp),%eeax ; 將j的的值裝入入到 EEAX maain+0 x22d: movvl -4(%ebpp),%edxx ; 將ii的值裝裝入到 EDXX mmainn+0 xx30: adddl %eaax,%edxx ; jj+i,結(jié)果存存入EDDX maiin+00 x322: lleall -00 xc(%ebbp),%eaax ; 將k的的地址裝裝入到EEAX maain+0 x335: adddl %edxx,(%eaxx) ; i+j+kk,結(jié)果果存入地地址ebbp-00 xc即即k中 maain+0 x337: mo

41、vvl -0 xcc(%eebp),%eeax ; 將kk的值裝裝入EAAX,作作為返回回值 maiin+00 x3aa: lleavve ; 撤銷SStacck FFramme maiin+00 x3bb: rret ; maiin函數(shù)數(shù)返回 問題:為什么么3個(gè)變變量分配配了0 xx18字字節(jié)的棧??臻g? 在在2個(gè)變變量的時(shí)時(shí)候,分分配??湛臻g的指指令是:subbl $8,%espp 而而在3個(gè)個(gè)局部變變量的時(shí)時(shí)候,分分配棧空空間的指指令是:subbl $0 x118,%espp 33個(gè)整型型變量只只需要00 xc字字節(jié),為為何實(shí)際際上分配配了0 xx18字字節(jié)呢? 答答案就是是:保持持16字字節(jié)棧對(duì)對(duì)齊。 在X886 匯匯編語言言學(xué)習(xí)手手記(11)里,已經(jīng)說說明過ggcc默默認(rèn)的編編譯是要要16字字節(jié)棧對(duì)對(duì)齊的,subbl $8,%espp會(huì)使棧棧16字字節(jié)對(duì)齊齊,而88字節(jié)空空間只能能滿足22個(gè)局部部變量,如果再再分配44字節(jié)滿滿足第33個(gè)局部部變量的的話,那那棧地址址就不再再16字字節(jié)對(duì)齊齊的,而而同時(shí)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論