亚洲欧美精品沙发,日韩在线精品视频,亚洲Av每日更新在线观看,亚洲国产另类一区在线5

<pre id="hdphd"></pre>

  • <div id="hdphd"><small id="hdphd"></small></div>
      學(xué)習(xí)啦>學(xué)習(xí)電腦>操作系統(tǒng)>Linux教程>

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      x1F,這個(gè)會(huì)在后面的具體分析中見(jiàn)到很多。

        (2)寄存器操作數(shù),它表示某個(gè)寄存器的內(nèi)容,用符號(hào)Ea來(lái)表示任意寄存器a,用引用R[Ea]來(lái)表示它的值,這是將寄存器集合看成一個(gè)數(shù)組R,用寄存器表示符作為索引。

        (3)操作數(shù)是存儲(chǔ)器引用,它會(huì)根據(jù)計(jì)算出來(lái)的地址(通常稱為有效地址)訪問(wèn)某個(gè)存儲(chǔ)器位置。用符號(hào)Mb[Addr]表示對(duì)存儲(chǔ)在存儲(chǔ)器中從地址Addr開(kāi)始的b字節(jié)值的引用。通??梢允÷韵聵?biāo)b。

        略過(guò),具體參考《深入理解計(jì)算機(jī)系統(tǒng)》

        2. 最簡(jiǎn)C代碼分析

        為簡(jiǎn)化問(wèn)題,來(lái)分析一下最簡(jiǎn)的c代碼生成的匯編代碼:

        # vi test1.c

        int main()

        {

        return 0;

        }

        編譯該程序,產(chǎn)生二進(jìn)制文件:

        # gcc test1.c -o test1

        # file test1

        test1: ELF 32-bit LSB executable 80386 Version 1, dynamically linked, 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 ; 反匯編main函數(shù),mdb的命令一般格式為 <地址>::dis

        main: pushl %ebp ; ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級(jí)調(diào)用函數(shù)的棧基地址

        main+1: movl %esp,%ebp ; esp值賦給ebp,設(shè)置main函數(shù)的?;?/p>

        main+3: subl ,%esp

        main+6: andl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      xf0,%esp

        main+9: movl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      ,%eax

        main+0xe: subl %eax,%esp

        main+0x10: movl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      ,%eax ; 設(shè)置函數(shù)返回值0

        main+0x15: leave ; 將ebp值賦給esp,pop先前棧內(nèi)的上級(jí)函數(shù)棧的基地址給ebp,恢復(fù)原?;?/p>

        main+0x16: ret ; main函數(shù)返回,回到上級(jí)調(diào)用

        >

        注:這里得到的匯編語(yǔ)言語(yǔ)法格式與Intel的手冊(cè)有很大不同,Unix/Linux采用AT&T匯編格式作為匯編語(yǔ)言的語(yǔ)法格式

        如果想了解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:

        > _start::dis ;從_start 的地址開(kāi)始反匯編

        _start: pushl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

        _start+2: pushl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

        _start+4: movl %esp,%ebp

        _start+6: pushl %edx

        _start+7: movl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      x80504b0,%eax

        _start+0xc: testl %eax,%eax

        _start+0xe: je +0xf <_start+0x1d>

        _start+0x10: pushl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      x80504b0

        _start+0x15: call -0x75 <atexit>

        _start+0x1a: addl ,%esp

        _start+0x1d: movl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      x8060710,%eax

        _start+0x22: testl %eax,%eax

        _start+0x24: je +7 <_start+0x2b>

        _start+0x26: call -0x86 <atexit>

        _start+0x2b: pushl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      x80506cd

        _start+0x30: call -0x90 <atexit>

        _start+0x35: movl +8(%ebp),%eax

        _start+0x38: leal +0x10(%ebp,%eax,4),%edx

        _start+0x3c: movl %edx,0x8060804

        _start+0x42: andl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      xf0,%esp

        _start+0x45: subl ,%esp

        _start+0x48: pushl %edx

        _start+0x49: leal +0xc(%ebp),%edx

        _start+0x4c: pushl %edx

        _start+0x4d: pushl %eax

        _start+0x4e: call +0x152 <_init>

        _start+0x53: call -0xa3 <__fpstart>

        _start+0x58: call +0xfb <main> ;在這里調(diào)用了main函數(shù)

        _start+0x5d: addl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      xc,%esp

        _start+0x60: pushl %eax

        _start+0x61: call -0xa1 <exit>

        _start+0x66: pushl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        _start+0x6d: lcall ,

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

        _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(Application Binary Interface)來(lái)決定的。

        Solaris/Linux操作系統(tǒng)的ABI就是Sytem V ABI。

        概念:SFP (Stack Frame Pointer) ??蚣苤羔?/p>

        正確理解SFP必須了解:

        IA32 的棧的概念

        CPU 中32位寄存器ESP/EBP的作用

        PUSH/POP 指令是如何影響棧的

        CALL/RET/LEAVE 等指令是如何影響棧的

        如我們所知:

        1)IA32的棧是用來(lái)存放臨時(shí)數(shù)據(jù),而且是LIFO,即后進(jìn)先出的。棧的增長(zhǎng)方向是從高地址向低地址增長(zhǎng),按字節(jié)為單位編址。

        2) EBP是?;返闹羔?,永遠(yuǎn)指向棧底(高地址),ESP是棧指針,永遠(yuǎn)指向棧頂(低地址)。

        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從棧內(nèi)彈出,放入一個(gè)32位寄存器。

        5) CALL指令用來(lái)調(diào)用一個(gè)函數(shù)或過(guò)程,此時(shí),下一條指令地址會(huì)被壓入堆棧,以備返回時(shí)能恢復(fù)執(zhí)行下條指令。

        6) RET指令用來(lái)從一個(gè)函數(shù)或過(guò)程返回,之前CALL保存的下條指令地址會(huì)從棧內(nèi)彈出到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)于以下兩條指令:

        movl ebp esp

        popl ebp

        如果反匯編一個(gè)函數(shù),很多時(shí)候會(huì)在函數(shù)進(jìn)入和返回處,發(fā)現(xiàn)有類似如下形式的匯編語(yǔ)句:

        pushl %ebp ; ebp寄存器內(nèi)容壓棧,即保存main函數(shù)的上級(jí)調(diào)用函數(shù)的?;刂?/p>

        movl %esp,%ebp ; esp值賦給ebp,設(shè)置 main函數(shù)的?;?/p>

        ........... ; 以上兩條指令相當(dāng)于 enter 0,0

        ...........

        leave ; 將ebp值賦給esp,pop先前棧內(nèi)的上級(jí)函數(shù)棧的基地址給ebp,恢復(fù)原?;?/p>

        ret ; main函數(shù)返回,回到上級(jí)調(diào)用

        這些語(yǔ)句就是用來(lái)創(chuàng)建和釋放一個(gè)函數(shù)或者過(guò)程的??蚣艿摹?/p>

        原來(lái)編譯器會(huì)自動(dòng)在函數(shù)入口和出口處插入創(chuàng)建和釋放??蚣艿恼Z(yǔ)句。

        函數(shù)被調(diào)用時(shí):

        1) EIP/EBP成為新函數(shù)棧的邊界

        函數(shù)被調(diào)用時(shí),返回時(shí)的EIP首先被壓入堆棧;創(chuàng)建??蚣軙r(shí),上級(jí)函數(shù)棧的EBP被壓入堆棧,與EIP一道行成新函數(shù)棧框架的邊界

        2) EBP成為??蚣苤羔楽FP,用來(lái)指示新函數(shù)棧的邊界

        棧框架建立后,EBP指向的棧的內(nèi)容就是上一級(jí)函數(shù)棧的EBP,可以想象,通過(guò)EBP就可以把層層調(diào)用函數(shù)的棧都回朔遍歷一遍,調(diào)試器就是利用這個(gè)特性實(shí)現(xiàn) backtrace功能的

        3) ESP總是作為棧指針指向棧頂,用來(lái)分配??臻g

        棧分配空間給函數(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) ; 函數(shù)入口參數(shù)的的訪問(wèn)

        -xx(%ebp) ; 函數(shù)局部變量訪問(wèn)

        假如函數(shù)A調(diào)用函數(shù)B,函數(shù)B調(diào)用函數(shù)C ,則函數(shù)??蚣芗罢{(diào)用關(guān)系如下圖所示:

        +-------------------------+----> 高地址

        | EIP (上級(jí)函數(shù)返回地址) |

        +-------------------------+

        +--> | EBP (上級(jí)函數(shù)的EBP) | --+ <------當(dāng)前函數(shù)A的EBP (即SFP框架指針)

        | +-------------------------+ +-->偏移量A

        | | Local Variables | |

        | | .......... | --+ <------ESP指向函數(shù)A新分配的局部變量,局部變量可以通過(guò)A的ebp-偏移量A訪問(wèn)

        | f +-------------------------+

        | r | Arg n(函數(shù)B的第n個(gè)參數(shù)) |

        | a +-------------------------+

        | m | Arg .(函數(shù)B的第.個(gè)參數(shù)) |

        | e +-------------------------+

        | | Arg 1(函數(shù)B的第1個(gè)參數(shù)) |

        | o +-------------------------+

        | f | Arg 0(函數(shù)B的第0個(gè)參數(shù)) | --+ <------ B函數(shù)的參數(shù)可以由B的ebp+偏移量B訪問(wèn)

        | +-------------------------+ +--> 偏移量B

        | A | EIP (A函數(shù)的返回地址) | |

        | +-------------------------+ --+

        +--- | EBP (A函數(shù)的EBP) |<--+ <------ 當(dāng)前函數(shù)B的EBP (即SFP框架指針)

        +-------------------------+ |

        | Local Variables | |

        | .......... | | <------ ESP指向函數(shù)B新分配的局部變量

        +-------------------------+ |

        | Arg n(函數(shù)C的第n個(gè)參數(shù)) | |

        +-------------------------+ |

        | Arg .(函數(shù)C的第.個(gè)參數(shù)) | |

        +-------------------------+ +--> frame of B

        | Arg 1(函數(shù)C的第1個(gè)參數(shù)) | |

        +-------------------------+ |

        | Arg 0(函數(shù)C的第0個(gè)參數(shù)) | |

        +-------------------------+ |

        | EIP (B函數(shù)的返回地址) | |

        +-------------------------+ |

        +--> | EBP (B函數(shù)的EBP) | --+ <------ 當(dāng)前函數(shù)C的EBP (即SFP框架指針)

        | +-------------------------+

        | | Local Variables |

        | | .......... | <------ ESP指向函數(shù)C新分配的局部變量

        | +-------------------------+----> 低地址

        frame of C

        圖 1-1

        再分析test1反匯編結(jié)果中剩余部分語(yǔ)句的含義:

        # mdb test1

        Loading modules: [ libc.so.1 ]

        > main::dis ; 反匯編main函數(shù)

        main: pushl %ebp

        main+1: movl %esp,%ebp ; 創(chuàng)建Stack Frame(??蚣?

        main+3: subl ,%esp ; 通過(guò)ESP-8來(lái)分配8字節(jié)堆??臻g

        main+6: andl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      xf0,%esp ; 使棧地址16字節(jié)對(duì)齊

        main+9: movl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      ,%eax ; 無(wú)意義

        main+0xe: subl %eax,%esp ; 無(wú)意義

        main+0x10: movl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      ,%eax ; 設(shè)置main函數(shù)返回值

        main+0x15: leave ; 撤銷Stack Frame(??蚣?

        main+0x16: ret ; main 函數(shù)返回

        >

        以下兩句似乎是沒(méi)有意義的,果真是這樣嗎?

        movl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      ,%eax

        subl %eax,%esp

        用gcc的O2級(jí)優(yōu)化來(lái)重新編譯test1.c:

        # gcc -O2 test1.c -o test1

        # mdb test1

        > main::dis

        main: pushl %ebp

        main+1: movl %esp,%ebp

        main+3: subl ,%esp

        main+6: andl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      xf0,%esp

        main+9: xorl %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)證了之前的猜測(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

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      ,%eax 變?yōu)?xorl %eax,%eax ,這是因?yàn)镮A32指令中,xorl比movl有更高的運(yùn)行速度。

        概念:Stack aligned 棧對(duì)齊

        那么,以下語(yǔ)句到底是和作用呢?

        subl ,%esp

        andl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      xf0,%esp ; 通過(guò)andl使低4位為0,保證棧地址16字節(jié)對(duì)齊

        表面來(lái)看,這條語(yǔ)句最直接的后果是使ESP的地址后4位為0,即16字節(jié)對(duì)齊,那么為什么這么做呢?

        原來(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

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      xf0,%esp 的意義很明顯,那么 subl ,%esp 呢,是必須的嗎?

        這里假設(shè)在進(jìn)入main函數(shù)之前,棧是16字節(jié)對(duì)齊的話,那么,進(jìn)入main函數(shù)后,EIP和EBP被壓入堆棧后,棧地址最末4位二進(jìn)制位必定是1000,esp -8則恰好使后4位地址二進(jìn)制位為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ì)齊指令:

        # gcc -mpreferred-stack-boundary=2 test1.c -o test1

        > main::dis

        main: pushl %ebp

        main+1: movl %esp,%ebp

        main+3: movl

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      ,%eax

        main+8: leave

        main+9: ret

        >

        可以看到,棧對(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

      Linux下GDB反匯編和調(diào)試

      時(shí)間: 志藝942 分享

        Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。

        LINUX下GDB反匯編和調(diào)試

        1、 基本操作指令

        簡(jiǎn)單的操作數(shù)類型說(shuō)明,一般有三種,

        (1)立即數(shù)操作數(shù),也就是常數(shù)值。立即數(shù)的書寫方式是“$”后面跟一個(gè)整數(shù),比如

      ,%eax

        main+5: ret

        >

        由此可知,-fomit-frame-pointer 可以去除SFP。

        問(wèn)題:去除SFP后有什么缺點(diǎn)呢?

        1)增加調(diào)式難度

        由于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)呢?

        1)節(jié)省??臻g

        2)減少建立和撤銷棧框架的指令后,簡(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)制接口

        函數(shù)如何找到它的參數(shù)?

        函數(shù)如何返回結(jié)果?

        函數(shù)在哪里存放局部變量?

        那一個(gè)硬件寄存器是起始空間?

        那一個(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 10的10大新變化

        3. 小結(jié)

        本文通過(guò)最簡(jiǎn)的C程序,引入以下概念:

        SFP ??蚣苤羔?/p>

        Stack aligned 棧對(duì)齊

        Calling 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)試技巧成為了可能。


      看了“LINUX下GDB反匯編和調(diào)試”還想看:

      1.編譯和調(diào)試的區(qū)別

      2.Ubuntu如何使用命令調(diào)節(jié)屏幕亮度

      3.Linux系統(tǒng)中如何調(diào)整swap大小

      4.Linux系統(tǒng)怎樣調(diào)整屏幕亮度

      5.Ubuntu下如何編輯開(kāi)始菜單

      Linux下GDB反匯編和調(diào)試

      Linux下的匯編與Windows匯編最大的不同就是第一個(gè)操作數(shù)是原操作數(shù),第二個(gè)是目的操作數(shù),而Windows下卻是相反。接下來(lái)是小編為大家收集的LINUX下GDB反匯編和調(diào)試,希望能幫到大家。 LINUX下GDB反匯編和調(diào)試 1、 基本操作指令 簡(jiǎn)單的操
      推薦度:
      點(diǎn)擊下載文檔文檔為doc格式
      2805004