




版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、 . X86匯編語(yǔ)言學(xué)習(xí)手記X86匯編語(yǔ)言學(xué)習(xí)手記(1)1. 編譯環(huán)境 OS: Solaris 9 X86 Compiler: gcc 3.3.2 Linker: Solaris Link Editors 5.x Debug Tool: mdb Editor: vi 注:關(guān)于編譯環(huán)境的安裝和設(shè)置,可以參考文章:Solaris 上的開(kāi)發(fā)環(huán)境安裝與設(shè)置。 mdb是Sola
2、ris提供的kernel debug工具,這里用它做反匯編和匯編語(yǔ)言調(diào)試工具。 如果在Linux平臺(tái)可以用gdb進(jìn)行反匯編和調(diào)試。 2. 最簡(jiǎn)C代碼分析 為簡(jiǎn)化問(wèn)題,來(lái)分析一下最簡(jiǎn)的c代碼生成的匯編代碼: # vi test1.c int main()
3、; return 0; 編譯該程序,產(chǎn)生二進(jìn)制文件: # gcc test1.c -o test1 # file test1 test1: ELF 32-bit LSB executable 80386 Version 1, dynamically linked
4、, not stripped test1是一個(gè)ELF格式32位小端(Little Endian)的可執(zhí)行文件,動(dòng)態(tài)并且符號(hào)表沒(méi)有去除。 這正是Unix/Linux平臺(tái)典型的可執(zhí)行文件格式。 用mdb反匯編可以觀察生成的匯編代碼: # mdb test1 Loading modules: libc.so.1 > main:dis &
5、#160; ; 反匯編main函數(shù),mdb的命令一般格式為 <地址>:dis main: pushl %ebp
6、0; ; ebp寄存器容壓棧,即保存main函數(shù)的上級(jí)調(diào)用函數(shù)的?;刂? main+1: movl %esp,%ebp ; esp值賦給ebp,設(shè)置main函數(shù)的?;? main+3: subl $8,%esp
7、 main+6: andl $0xf0,%esp main+9: movl $0,%eax main+0xe: subl
8、0; %eax,%esp main+0x10: movl $0,%eax ; 設(shè)置函數(shù)返回值0 main+0x15: leave ; 將ebp值賦給esp,pop先前棧的上級(jí)函數(shù)棧的基地址給ebp,恢
9、復(fù)原?;? main+0x16: ret ; main函數(shù)返回,回到上級(jí)調(diào)用 > 注:這里得到的匯編語(yǔ)言語(yǔ)法格式與Intel的手冊(cè)有很大不同,Unix/Linux采用AT&T匯編格式作為匯編語(yǔ)言的語(yǔ)法格式 &
10、#160; 如果想了解AT&T匯編可以參考文章:Linux AT&T 匯編語(yǔ)言開(kāi)發(fā)指南 問(wèn)題:誰(shuí)調(diào)用了 main函數(shù)? 在C語(yǔ)言的層面來(lái)看,main函數(shù)是一個(gè)程序的起始入口點(diǎn),而實(shí)際上,ELF可執(zhí)行文件的入口點(diǎn)并不是main而是_start。 mdb也可以反匯編_start:
11、; > _start:dis ;從_start 的地址開(kāi)始反匯編 _start:
12、60; pushl $0 _start+2: pushl $0 _start+4: movl %esp,%ebp
13、_start+6: pushl %edx _start+7: movl $0x80504b0,%eax _start+0xc: &
14、#160; testl %eax,%eax _start+0xe: je +0xf <_start+0x1d> _start+0x10:
15、160; pushl $0x80504b0 _start+0x15: call -0x75 <atexit> _start+0x1a:
16、60; addl $4,%esp _start+0x1d: movl $0x8060710,%eax _start+0x22: testl %eax,%eax
17、160; _start+0x24: je +7 <_start+0x2b> _start+0x26: call
18、0; -0x86 <atexit> _start+0x2b: pushl $0x80506cd _start+0x30: call -0x9
19、0 <atexit> _start+0x35: movl +8(%ebp),%eax _start+0x38: leal +0x
20、10(%ebp,%eax,4),%edx _start+0x3c: movl %edx,0x8060804 _start+0x42: andl $0xf0,%esp _start+0x45:
21、0; subl $4,%esp _start+0x48: pushl %edx _start+0x49: leal +0xc(%ebp),%edx
22、160; _start+0x4c: pushl %edx _start+0x4d: pushl %eax _start+0x4e: call +0x15
23、2 <_init> _start+0x53: call -0xa3 <_fpstart> _start+0x58: &
24、#160; call +0xfb <main> ;在這里調(diào)用了main函數(shù) _start+0x5d: addl
25、0; $0xc,%esp _start+0x60: pushl %eax _start+0x61: call -0xa1 <exit&
26、gt; _start+0x66: pushl $0 _start+0x68: movl $1,%eax _start+0x6d: lcal
27、l $7,$0 _start+0x74: hlt > 問(wèn)題:為什么用EAX寄存器保存函數(shù)返回值? 實(shí)際上IA32并沒(méi)有規(guī)定用哪個(gè)寄存器來(lái)保存返回值。但如果反匯編Solaris/Linux的二進(jìn)制文件,就會(huì)發(fā)現(xiàn),都用EAX保存函數(shù)返回值。 這不是偶然現(xiàn)象,是操作系統(tǒng)的ABI
28、(Application Binary Interface)來(lái)決定的。 Solaris/Linux操作系統(tǒng)的ABI就是Sytem V ABI。 概念:SFP (Stack Frame Pointer) ??蚣苤羔?#160; 正確理解SFP必須了解: IA32 的棧的概念 CPU 中32位寄存器ESP/EBP的作
29、用 PUSH/POP 指令是如何影響棧的 CALL/RET/LEAVE 等指令是如何影響棧的 如我們所知: 1)IA32的棧是用來(lái)存放臨時(shí)數(shù)據(jù),而且是LIFO,即后進(jìn)先出的。棧的增長(zhǎng)方向是從高地址向低地址增長(zhǎng),按字節(jié)為單位編址。 2) EBP是?;返闹羔槪肋h(yuǎn)指向棧底(高地址),ESP是棧指針,永遠(yuǎn)指向棧頂(低
30、地址)。 3) PUSH一個(gè)long型數(shù)據(jù)時(shí),以字節(jié)為單位將數(shù)據(jù)壓入棧,從高到低按字節(jié)依次將數(shù)據(jù)存入ESP-1、ESP-2、ESP-3、ESP-4的地址單元。 4) POP一個(gè)long型數(shù)據(jù),過(guò)程與PUSH相反,依次將ESP-4、ESP-3、ESP-2、ESP-1從棧彈出,放入一個(gè)32位寄存器。 5) CALL指令用來(lái)調(diào)用一個(gè)函數(shù)或過(guò)程,此時(shí),下一條指令地址會(huì)被壓入堆棧,以備返回時(shí)能恢復(fù)執(zhí)行下條指令。 6) RET指令用來(lái)從一個(gè)函數(shù)或過(guò)程返回,
31、之前CALL保存的下條指令地址會(huì)從棧彈出到EIP寄存器中,程序轉(zhuǎn)到CALL之前下條指令處執(zhí)行 7) ENTER是建立當(dāng)前函數(shù)的??蚣?,即相當(dāng)于以下兩條指令: pushl %ebp movl %esp,%ebp 8) LEAVE是釋放當(dāng)前函數(shù)或者過(guò)程的??蚣埽聪喈?dāng)于以下兩條指令:
32、; movl ebp esp popl ebp 如果反匯編一個(gè)函數(shù),很多時(shí)候會(huì)在函數(shù)進(jìn)入和返回處,發(fā)現(xiàn)有類(lèi)似如下形式的匯編語(yǔ)句: pushl %ebp
33、; ; ebp寄存器容壓棧,即保存main函數(shù)的上級(jí)調(diào)用函數(shù)的?;刂? movl %esp,%ebp ; esp值賦給ebp,設(shè)置 main函數(shù)的?;? .
34、0; ; 以上兩條指令相當(dāng)于 enter 0,0 . leave ; 將ebp值賦給esp,pop先前棧的上級(jí)函數(shù)棧的基地址給e
35、bp,恢復(fù)原?;? ret ; main函數(shù)返回,回到上級(jí)調(diào)用 這些語(yǔ)句就是用來(lái)創(chuàng)建和釋放一個(gè)函數(shù)或者過(guò)程的棧框架的。 原來(lái)編譯器會(huì)自動(dòng)在函數(shù)入口和出口處插入創(chuàng)建和釋放??蚣艿恼Z(yǔ)句。 &
36、#160; 函數(shù)被調(diào)用時(shí): 1) EIP/EBP成為新函數(shù)棧的邊界 函數(shù)被調(diào)用時(shí),返回時(shí)的EIP首先被壓入堆棧;創(chuàng)建棧框架時(shí),上級(jí)函數(shù)棧的EBP被壓入堆棧,與EIP一道行成新函數(shù)??蚣艿倪吔? 2) EBP成為棧框架指針SFP,用來(lái)指示新函數(shù)棧的邊界 ??蚣芙⒑螅珽BP指向的棧的容就是上一級(jí)函數(shù)棧的EBP,可以想象,通過(guò)EBP就可以把層層調(diào)用函數(shù)的棧都回朔遍歷一遍,調(diào)試器就是利用這個(gè)特性實(shí)現(xiàn) backtrace功能的 &
37、#160; 3) ESP總是作為棧指針指向棧頂,用來(lái)分配棧空間 棧分配空間給函數(shù)局部變量時(shí)的語(yǔ)句通常就是給ESP減去一個(gè)常數(shù)值,例如,分配一個(gè)整型數(shù)據(jù)就是 ESP-4 4) 函數(shù)的參數(shù)傳遞和局部變量訪問(wèn)可以通過(guò)SFP即EBP來(lái)實(shí)現(xiàn) 由于棧框架指針永遠(yuǎn)指向當(dāng)前函數(shù)的?;刂?,參數(shù)和局部變量訪問(wèn)通常為如下形式: +8+xx(%ebp)
38、0; ; 函數(shù)入口參數(shù)的的訪問(wèn) -xx(%ebp) ; 函數(shù)局部變量訪問(wèn) 假如函數(shù)A調(diào)用函數(shù)B,函數(shù)B調(diào)用函數(shù)C ,則函數(shù)??蚣芘c調(diào)用關(guān)系如下圖所示: b:771
39、101bbb0下圖有點(diǎn)亂,因此刪去部分容,要看原圖可參考我的blog/b:771101bbb0 +-+-> 高地址 | EIP (上級(jí)函數(shù)返回地址) | +-+ | EBP (上級(jí)函數(shù)的EBP) | +-+ | Local Variables | | .
40、160; | +-+ | Arg n(函數(shù)B的第n個(gè)參數(shù)) | +-+ | Arg .(函數(shù)B的第.個(gè)參數(shù)) | +-+ | Arg 1(函數(shù)B的第1個(gè)參數(shù)) | +-+ | Arg 0(函數(shù)
41、B的第0個(gè)參數(shù)) | +-+ EIP (A函數(shù)的返回地址) | +-+ | EBP (A函數(shù)的EBP) | +-+ | Local Variables | | .
42、60; | +-+ | Arg n(函數(shù)C的第n個(gè)參數(shù)) | +-+ | Arg .(函數(shù)C的第.個(gè)參數(shù)) | +-+ | Arg 1(函數(shù)C的
43、第1個(gè)參數(shù)) | +-+ | Arg 0(函數(shù)C的第0個(gè)參數(shù)) | +-+ | EIP (B函數(shù)的返回地址) | +-+ | EBP (B函數(shù)的EBP) | +-+ | Local Variables
44、160; | | . | +-+-> 低地址 圖 1-1 再分析test1反匯編結(jié)果
45、中剩余部分語(yǔ)句的含義: # mdb test1 Loading modules: libc.so.1 > main:dis
46、0; ; 反匯編main函數(shù) main: pushl %ebp
47、60; main+1: movl %esp,%ebp ; 創(chuàng)建Stack Frame(??蚣? main+3: subl $8,%esp ; 通過(guò)ESP-8來(lái)分配8字
48、節(jié)堆??臻g main+6: andl $0xf0,%esp ; 使棧地址16字節(jié)對(duì)齊 main+9: movl $0,%eax ; 無(wú)意義 main+0xe:
49、160; subl %eax,%esp ; 無(wú)意義 main+0x10: movl $0,%eax ; 設(shè)置main函數(shù)返回值 main+0x15: leave
50、160; ; 撤銷(xiāo)Stack Frame(??蚣? main+0x16: ret &
51、#160; ; main 函數(shù)返回 > 以下兩句似乎是沒(méi)有意義的,果真是這樣嗎? movl $0,%eax subl %eax,%esp &
52、#160; 用gcc的O2級(jí)優(yōu)化來(lái)重新編譯test1.c: # gcc -O2 test1.c -o test1 # mdb test1 > main:dis main: pushl %ebp main+1:
53、160; movl %esp,%ebp main+3: subl $8,%esp main+6: andl $0xf0,%esp main+9: xo
54、rl %eax,%eax ; 設(shè)置main返回值,使用xorl異或指令來(lái)使eax為0 main+0xb: leave main+0xc: ret > 新的反匯編結(jié)果比最初的結(jié)果要簡(jiǎn)潔一些,果然之前被認(rèn)為無(wú)用的語(yǔ)句被優(yōu)化掉了,進(jìn)一步驗(yàn)證了之
55、前的猜測(cè)。 提示:編譯器產(chǎn)生的某些語(yǔ)句可能在程序?qū)嶋H語(yǔ)義上沒(méi)有用處,可以用優(yōu)化選項(xiàng)去掉這些語(yǔ)句。 問(wèn)題:為什么用xorl來(lái)設(shè)置eax的值? 注意到優(yōu)化后的代碼中,eax返回值的設(shè)置由 movl $0,%eax 變?yōu)?xorl %eax,%eax ,這是因?yàn)镮A32指令中,xorl比movl有更高的運(yùn)行速度。 概念:Stack aligned 棧對(duì)齊 那么,以下語(yǔ)句到底是和作用呢? &
56、#160; subl $8,%esp andl $0xf0,%esp ; 通過(guò)andl使低4位為0,保證棧地址16字節(jié)對(duì)齊 表面來(lái)看,這條語(yǔ)句最直接的后果是使ESP的地址后4位為0,即16字節(jié)對(duì)齊,那么為什么這么做呢? &
57、#160; 原來(lái),IA32 系列CPU的一些指令分別在4、8、16字節(jié)對(duì)齊時(shí)會(huì)有更快的運(yùn)行速度,因此gcc編譯器為提高生成代碼在IA32上的運(yùn)行速度,默認(rèn)對(duì)產(chǎn)生的代碼進(jìn)行16字節(jié)對(duì)齊 andl $0xf0,%esp 的意義很明顯,那么 subl $8,%esp 呢,是必須的嗎? 這里假設(shè)在進(jìn)入main函數(shù)之前,棧是16字節(jié)對(duì)齊的話,那么,進(jìn)入main函數(shù)后,EIP和EBP被壓入堆棧后,棧地址最末4位二進(jìn)制位必定是 1000,esp -8則恰好使后4位地址二進(jìn)制
58、位為0000。看來(lái),這也是為保證棧16字節(jié)對(duì)齊的。 如果查一下gcc的手冊(cè),就會(huì)發(fā)現(xiàn)關(guān)于棧對(duì)齊的參數(shù)設(shè)置: -mpreferred-stack-boundary=n ; 希望棧按照2的n次的字節(jié)邊界對(duì)齊, n的取值圍是2-12 默認(rèn)情況下,n是等于4的,也就是說(shuō),默認(rèn)情況下,gcc是16字節(jié)對(duì)齊,以適應(yīng)IA32大多數(shù)指令的要求。 讓我們利用-mpreferred-stack-boundary=2來(lái)去除棧對(duì)齊指
59、令: # gcc -mpreferred-stack-boundary=2 test1.c -o test1 > main:dis main: pushl %ebp main+1:
60、60; movl %esp,%ebp main+3: movl $0,%eax main+8: leave main+9: ret > 可以
61、看到,棧對(duì)齊指令沒(méi)有了,因?yàn)?,IA32的棧本身就是4字節(jié)對(duì)齊的,不需要用額外指令進(jìn)行對(duì)齊。 那么,??蚣苤羔楽FP是不是必須的呢? # gcc -mpreferred-stack-boundary=2 -fomit-frame-pointer test1.c -o test > main:dis main: movl $0,%eax
62、 main+5: ret > 由此可知,-fomit-frame-pointer 可以去除SFP。 問(wèn)題:去除SFP后有什么缺點(diǎn)呢? 1)增加調(diào)式難度
63、0; 由于SFP在調(diào)試器backtrace的指令中被使用到,因此沒(méi)有SFP該調(diào)試指令就無(wú)法使用。 2)降低匯編代碼可讀性 函數(shù)參數(shù)和局部變量的訪問(wèn),在沒(méi)有ebp的情況下,都只能通過(guò)+xx(esp)的方式訪問(wèn),而很難區(qū)分兩種方式,降低了程序的可讀性。 問(wèn)題:去除SFP有什么優(yōu)點(diǎn)呢?
64、; 1)節(jié)省棧空間 2)減少建立和撤銷(xiāo)??蚣艿闹噶詈?,簡(jiǎn)化了代碼 3)使ebp空閑出來(lái),使之作為通用寄存器使用,增加通用寄存器的數(shù)量 4)以上3點(diǎn)使得程序運(yùn)行速度更快 概念:Calling Convention 調(diào)用約定和 ABI (Application Binary Interface) 應(yīng)用程序二進(jìn)制接口
65、 函數(shù)如何找到它的參數(shù)? 函數(shù)如何返回結(jié)果? 函數(shù)在哪里存放局部變量? 那一個(gè)硬件寄存器是起始空間?
66、; 那一個(gè)硬件寄存器必須預(yù)先保留? Calling Convention 調(diào)用約定對(duì)以上問(wèn)題作出了規(guī)定。Calling Convention也是ABI的一部分。 因此,遵守一樣ABI規(guī)的操作系統(tǒng),使其相互間實(shí)現(xiàn)二進(jìn)制代碼的互操作成為了可能。 例如:由于Solaris、Linux都遵守System V的ABI,Solaris 10就提供了直接運(yùn)行Linux二進(jìn)制程序的功能。 詳見(jiàn)文章:關(guān)注: Solaris 1
67、0的10大新變化 3. 小結(jié) 本文通過(guò)最簡(jiǎn)的C程序,引入以下概念: SFP ??蚣苤羔? Stack aligned 棧對(duì)齊 Calli
68、ng Convention 調(diào)用約定 和 ABI (Application Binary Interface) 應(yīng)用程序二進(jìn)制接口 今后,將通過(guò)進(jìn)一步的實(shí)驗(yàn),來(lái)深入了解這些概念。通過(guò)掌握這些概念,使在匯編級(jí)調(diào)試程序產(chǎn)生的core dump、掌握C語(yǔ)言高級(jí)調(diào)試技巧成為了可能。X86匯編語(yǔ)言學(xué)習(xí)手記(2)這是作者在學(xué)習(xí)X86匯編過(guò)程中的學(xué)習(xí)筆記,難免有錯(cuò)誤和疏漏之處,歡迎指正。作者將隨時(shí)修改錯(cuò)誤并將新的版本發(fā)布在自己的Blog站點(diǎn)上。嚴(yán)格說(shuō)來(lái),本篇文檔更側(cè)重于C語(yǔ)言和C編譯器方面的知識(shí),如果涉與到基本的匯編語(yǔ)言的容,可以參考相關(guān)文檔。 自X86 匯
69、編語(yǔ)言學(xué)習(xí)手記(1)在作者的Blog上發(fā)布以來(lái),得到了很多網(wǎng)友的肯定和鼓勵(lì),并且還有熱心網(wǎng)友指出了其中的錯(cuò)誤,b:bea66ddae0作者已經(jīng)將文檔中已發(fā)現(xiàn)的錯(cuò)誤修正后更新在Blog上。/b:bea66ddae0 上一篇文章通過(guò)分析一個(gè)最簡(jiǎn)的C程序,引出了以下概念: Stack Frame ??蚣?和 SFP ??蚣苤羔? Stack aligned 棧對(duì)齊
70、60; Calling Convention 調(diào)用約定 和 ABI (Application Binary Interface) 應(yīng)用程序二進(jìn)制接口 本章中,將通過(guò)進(jìn)一步的實(shí)驗(yàn),來(lái)深入了解這些概念。如果還不了解這些概念,可以參考 X86匯編語(yǔ)言學(xué)習(xí)手記(1)。 1. 局部變量的棧分配 上篇文章已經(jīng)分析過(guò)一個(gè)最簡(jiǎn)的C程序, 下面
71、我們分析一下C編譯器如何處理局部變量的分配,為此先給出如下程序: #vi test2.c int main() int i; int j=2; i=3; &
72、#160; i=+i; return i+j; 編譯該程序,產(chǎn)生二進(jìn)制文件,并利用mdb來(lái)觀察程序運(yùn)行中的stack的狀態(tài): #gcc test2.c -o test2 #mdb test2 Loading modules: libc.so.1 > main:dis
73、 main: pushl %ebp main+1: movl %esp,%ebp ; main至main+1,創(chuàng)建Stack Frame
74、160; main+3: subl $8,%esp ; 為局部變量i,j分配??臻g,并保證棧16字節(jié)對(duì)齊 main+6: andl $0xf0
75、,%esp main+9: movl $0,%eax main+0xe: subl %eax,%esp ; main+6至main+0xe,再次保證棧16字節(jié)對(duì)齊
76、 main+0x10: movl $2,-8(%ebp) ; 初始化局部變量j的值為2 main+0x17: movl $3,-4(%ebp) ; 給局部變量i賦值為
77、3 main+0x1e: leal -4(%ebp),%eax ; 將局部變量i的地址裝入到EAX寄存器中 main+0x21: incl (%eax)
78、 ; i+ main+0x23: movl -8(%ebp),%eax ; 將j的值裝入EAX main+0x26: addl -4(%ebp),%eax ; i+j并將結(jié)果存入EAX,作
79、為返回值 main+0x29: leave ; 撤銷(xiāo)Stack Frame main+0x2a: ret
80、 ; main函數(shù)返回 > > main+0x10:b ; 在地址 main+0x10處設(shè)置斷點(diǎn) > main+0x1e:b
81、0; ; 在main+0x1e設(shè)置斷點(diǎn) > main+0x29:b ; 在main+0x1e設(shè)置斷點(diǎn) > main+0x2a:b ; 在main+0x1e設(shè)置斷點(diǎn)
82、; 下面的mdb的4個(gè)命令在一行輸入,中間用分號(hào)間隔開(kāi),命令的含義在注釋中給出: > :r;<esp,10/nap;<ebp=X;<eax=X ; 運(yùn)行程序(:r 命令) mdb: stop at main+0x10 ; 以ESP寄存器為起始地址,指定格式輸出16字節(jié)的棧
83、容(<esp,10/nap 命令) mdb: target stopped at: ; 在最后輸出EBP和EAX寄存器的值(<ebp=X 命令 和<eax=X 命令) main+0x10: movl $2,-8(%ebp)
84、0; ; 程序運(yùn)行后在main +0x10處指令執(zhí)行前中斷,此時(shí)棧分配后還未初始化 0x8047db0: 0x8047db0: 0xddbebca0 ; 這是變量j,4字節(jié),未初始化,此處為棧頂,ESP的值就是0x8047d
85、b0 0x8047db4: 0xddbe137f ; 這是變量i, 4字節(jié),未初始化 0x8047db8: 0x8047dd8 &
86、#160; ; 這是_start的SFP(_start的EBP),4字節(jié),由main 的SFP指向它 0x8047dbc: _start+0x5d ; 這是_start調(diào)用main之前壓棧的下條指令地址,main返回后將恢復(fù)給EIP 0x8047dc0:
87、60; 1 0x8047dc4: 0x8047de4 0x8047dc8: 0x8047dec
88、; 0x8047dcc: _start+0x35 0x8047dd0: _fini 0x8047dd4:
89、; ld.so.1atexit_fini 0x8047dd8: 0 ; _start的SFP指向的容為0,證明_start是程序的入口 0x8047ddc:
90、0; 0 0x8047de0: 1 0x8047de4:
91、 0x8047eb4 0x8047de8: 0 0x8047dec: 0x804
92、7eba 8047db8 ; 這是main當(dāng)前EBP寄存器的值,即main的SFP
93、; 0 ; EAX的值,當(dāng)前為0 > :c;<esp,10/nap;<ebp=X;<eax=X ; 繼續(xù)運(yùn)行程序(:c
94、 命令),其余3命令同上,打印16字節(jié)棧和EBP,EAX容 mdb: stop at main+0x1e mdb: target stopped at: main+0x1e: leal -4(%ebp),%eax ; 程序運(yùn)行到斷點(diǎn)main+0x1e處停止,此時(shí)局部變量i,j賦值已完成 0x8047db0:
95、0; 0x8047db0: 2 ; 這是變量j,4字節(jié),值為2,此處為棧頂,ESP的值就是0x8047db0 0x8047db4:
96、; 3 ; 這是變量i,4字節(jié),值為3 0x8047db8: 0x8047dd8 &
97、#160; ; 這是_start的SFP,4字節(jié) 0x8047dbc: _start+0x5d ; 這是返回_start后的EIP 0x8047dc0: 1
98、0; 0x8047dc4: 0x8047de4 0x8047dc8: 0x8047dec 0x8047dcc:
99、160; _start+0x35 0x8047dd0: _fini 0x8047dd4: ld.so.1atexit_fini 0x8047dd8:&
100、#160; 0 0x8047ddc: 0 0x8047d
101、e0: 1 0x8047de4: 0x8047eb4 0x8047de8: 0&
102、#160; 0x8047dec: 0x8047eba
103、160; 8047db8 ; 這是main當(dāng)前EBP寄存器的值,即main的SFP 0
104、0; ; EAX的值,當(dāng)前為0 > :c;<esp,10/nap;<ebp=X;<eax=X ; 繼續(xù)運(yùn)行程序,打印16字節(jié)棧和EBP,EAX容 mdb: stop at main+0x29 mdb: target stopped at: main+0x29:
105、0; leave ; 運(yùn)行到斷點(diǎn)main+0x29處停止,計(jì)算已經(jīng)完成,即將撤銷(xiāo)Stack Frame 0x8047db0: 0x8047db0: 2 &
106、#160; ; 這是變量j,4字節(jié),值為2,此處為棧頂,ESP的值就是0x8047db0 0x8047db4: 4
107、160; ; 這是i+以后的變量i,4字節(jié),值為3 0x8047db8: 0x8047dd8 ; 這是_start的SFP,4字節(jié) 0x80
108、47dbc: _start+0x5d ; 這是返回_start后的EIP 0x8047dc0: 1
109、60; 0x8047dc4: 0x8047de4 0x8047dc8: 0x8047dec 0x8047dcc: _start+0x35
110、160; 0x8047dd0: _fini 0x8047dd4: ld.so.1atexit_fini 0x8047dd8: 0
111、; 0x8047ddc: 0 0x8047de0: 1 &
112、#160; 0x8047de4: 0x8047eb4 0x8047de8: 0 &
113、#160; 0x8047dec: 0x8047eba 8047db8
114、 ; 這是main當(dāng)前EBP寄存器的值,即main的SFP 6
115、0; ; EAX的值,即函數(shù)的返回值,當(dāng)前為6 > :c;<esp,10/nap;<ebp=X;<eax=X ; 繼續(xù)運(yùn)行程序,打印16字節(jié)棧和EBP,EAX容 mdb: stop at
116、main+0x2a mdb: target stopped at: main+0x2a: ret ; 運(yùn)行到斷點(diǎn)main+0x2a處停止,Stack Frame已被撤銷(xiāo),main即將返回 0x8047dbc: &
117、#160; 0x8047dbc: _start+0x5d ; Stack Frame已經(jīng)被撤銷(xiāo),棧頂是返回_start后的EIP,main的棧已被釋放 0x8047dc0: 1
118、 0x8047dc4: 0x8047de4 0x8047dc8: 0x8047dec
119、60; 0x8047dcc: _start+0x35 0x8047dd0: _fini 0x8047dd4: ld.so.1atexit_f
120、ini 0x8047dd8: 0 0x8047ddc: 0
121、; 0x8047de0: 1 0x8047de4: 0x8047eb4 0x8047de8
122、: 0 0x8047dec: 0x8047eba 0x8047df0: 0x80
123、47ed6 0x8047df4: 0x8047edd 0x8047df8: 0x8047ee4
124、0; 8047dd8 ; _start的SFP,之前存儲(chǔ)在地址0x8047db8處,main的Stack Frame撤銷(xiāo)時(shí)恢復(fù)
125、60; 6 ; EAX的值,即函數(shù)的返回值,當(dāng)前為6
126、60; > :s;<esp,10/nap;<ebp=X;<eax=X ; 單步執(zhí)行下條指令(:s 命令),打印16字節(jié)棧和EBP,EAX容 mdb: target stopped at: _start+0x5d: addl $0xc,%esp ; 此時(shí)main已經(jīng)返回,_start+0x5d曾經(jīng)存儲(chǔ)在地址0x8047dbc處
127、160; 0x8047dc0: 0x8047dc0: 1 ; main已經(jīng)返回,_start +0x5d已經(jīng)被彈出 0x8047dc4:
128、160; 0x8047de4 0x8047dc8: 0x8047dec 0x8047dcc: _start+0x35
129、; 0x8047dd0: _fini 0x8047dd4: ld.so.1atexit_fini 0x8047dd8: 0
130、60; ; _start的SFP指向的容為0,證明_start是程序的入口 0x8047ddc: 0
131、60; 0x8047de0: 1 0x8047de4: 0x8047eb4
132、60; 0x8047de8: 0 0x8047dec: 0x8047eba
133、160; 0x8047df0: 0x8047ed6 0x8047df4: 0x8047edd 0x8047df8: 0x8047ee4
134、60; 0x8047dfc: 0x8047ef3 8047dd8
135、160; ; _start的SFP,之前存儲(chǔ)在地址0x8047db8處,main的Stack Frame撤銷(xiāo)時(shí)恢復(fù) 6 ; EAX的值為6,還是main函數(shù)的返回值 > 通過(guò)m
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年自動(dòng)化儀表項(xiàng)目發(fā)展計(jì)劃
- 醫(yī)療機(jī)構(gòu)執(zhí)業(yè)醫(yī)師崗位全職聘用及醫(yī)療設(shè)備更新改造合同
- 系統(tǒng)安全審計(jì)補(bǔ)充協(xié)議
- 城市更新拆遷補(bǔ)償款分配與離婚房產(chǎn)分割協(xié)議書(shū)
- 有機(jī)嬰幼兒奶粉品牌授權(quán)與銷(xiāo)售渠道拓展協(xié)議
- 文旅產(chǎn)業(yè)投資基金合作管理協(xié)議
- 展覽會(huì)現(xiàn)場(chǎng)藝術(shù)品鑒定及補(bǔ)充服務(wù)協(xié)議
- 虛擬角色影視制作租賃合同及版權(quán)轉(zhuǎn)讓協(xié)議
- 2025年運(yùn)載火箭遙測(cè)系統(tǒng)檢測(cè)設(shè)備項(xiàng)目建議書(shū)
- 科技研發(fā)人員兼職競(jìng)業(yè)限制與成果歸屬協(xié)議
- 安徽省1號(hào)卷A10聯(lián)盟2025屆高三5月最后一卷語(yǔ)文試題及答案
- 2025屆金融行業(yè)校招面試真題及答案
- 環(huán)保再生塑料椅行業(yè)深度調(diào)研及發(fā)展戰(zhàn)略咨詢(xún)報(bào)告
- 初中生物會(huì)考試卷及答案2024
- 河北省邢臺(tái)市一中等校2024-2025學(xué)年高二下學(xué)期期中語(yǔ)文試題(含答案)
- 2025-2030中國(guó)高壓變頻器行業(yè)市場(chǎng)深度調(diào)研及投資價(jià)值與投資前景研究報(bào)告
- 2025年游戲開(kāi)發(fā)與設(shè)計(jì)專(zhuān)業(yè)考試試卷及答案
- 少先隊(duì)的測(cè)試題及答案
- 煤炭工業(yè)礦井建設(shè)巖土工程勘察規(guī)范
- 職業(yè)技術(shù)學(xué)院食品質(zhì)量與安全專(zhuān)業(yè)《食品化學(xué)》課程標(biāo)準(zhǔn)
- 公共組織績(jī)效評(píng)估-形考任務(wù)二(占10%)-國(guó)開(kāi)(ZJ)-參考資料
評(píng)論
0/150
提交評(píng)論