• <output id="aynwq"><form id="aynwq"><code id="aynwq"></code></form></output>

    <mark id="aynwq"><option id="aynwq"></option></mark>
  • <mark id="aynwq"><option id="aynwq"></option></mark><label id="aynwq"><dl id="aynwq"></dl></label>
  • 學習啦>學習電腦>操作系統>Linux教程>

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    x1F,這個會在后面的具體分析中見到很多。

      (2)寄存器操作數,它表示某個寄存器的內容,用符號Ea來表示任意寄存器a,用引用R[Ea]來表示它的值,這是將寄存器集合看成一個數組R,用寄存器表示符作為索引。

      (3)操作數是存儲器引用,它會根據計算出來的地址(通常稱為有效地址)訪問某個存儲器位置。用符號Mb[Addr]表示對存儲在存儲器中從地址Addr開始的b字節值的引用。通常可以省略下標b。

      略過,具體參考《深入理解計算機系統》

      2. 最簡C代碼分析

      為簡化問題,來分析一下最簡的c代碼生成的匯編代碼:

      # vi test1.c

      int main()

      {

      return 0;

      }

      編譯該程序,產生二進制文件:

      # gcc test1.c -o test1

      # file test1

      test1: ELF 32-bit LSB executable 80386 Version 1, dynamically linked, not stripped

      test1是一個ELF格式32位小端(Little Endian)的可執行文件,動態鏈接并且符號表沒有去除。

      這正是Unix/Linux平臺典型的可執行文件格式。

      用mdb反匯編可以觀察生成的匯編代碼:

      # mdb test1

      Loading modules: [ libc.so.1 ]

      > main::dis ; 反匯編main函數,mdb的命令一般格式為 <地址>::dis

      main: pushl %ebp ; ebp寄存器內容壓棧,即保存main函數的上級調用函數的棧基地址

      main+1: movl %esp,%ebp ; esp值賦給ebp,設置main函數的棧基址

      main+3: subl ,%esp

      main+6: andl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    xf0,%esp

      main+9: movl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    ,%eax

      main+0xe: subl %eax,%esp

      main+0x10: movl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    ,%eax ; 設置函數返回值0

      main+0x15: leave ; 將ebp值賦給esp,pop先前棧內的上級函數棧的基地址給ebp,恢復原棧基址

      main+0x16: ret ; main函數返回,回到上級調用

      >

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

      如果想了解AT&T匯編可以參考文章:Linux AT&T 匯編語言開發指南

      問題:誰調用了 main函數?

      在C語言的層面來看,main函數是一個程序的起始入口點,而實際上,ELF可執行文件的入口點并不是main而是_start。

      mdb也可以反匯編_start:

      > _start::dis ;從_start 的地址開始反匯編

      _start: pushl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

      _start+2: pushl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

      _start+4: movl %esp,%ebp

      _start+6: pushl %edx

      _start+7: movl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    x80504b0,%eax

      _start+0xc: testl %eax,%eax

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

      _start+0x10: pushl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    x80504b0

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

      _start+0x1a: addl ,%esp

      _start+0x1d: movl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    x8060710,%eax

      _start+0x22: testl %eax,%eax

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

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

      _start+0x2b: pushl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    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反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    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> ;在這里調用了main函數

      _start+0x5d: addl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    xc,%esp

      _start+0x60: pushl %eax

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

      _start+0x66: pushl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      _start+0x6d: lcall ,

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

      _start+0x74: hlt

      >

      問題:為什么用EAX寄存器保存函數返回值?

      實際上IA32并沒有規定用哪個寄存器來保存返回值。但如果反匯編Solaris/Linux的二進制文件,就會發現,都用EAX保存函數返回值。

      這不是偶然現象,是操作系統的ABI(Application Binary Interface)來決定的。

      Solaris/Linux操作系統的ABI就是Sytem V ABI。

      概念:SFP (Stack Frame Pointer) 棧框架指針

      正確理解SFP必須了解:

      IA32 的棧的概念

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

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

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

      如我們所知:

      1)IA32的棧是用來存放臨時數據,而且是LIFO,即后進先出的。棧的增長方向是從高地址向低地址增長,按字節為單位編址。

      2) EBP是棧基址的指針,永遠指向棧底(高地址),ESP是棧指針,永遠指向棧頂(低地址)。

      3) PUSH一個long型數據時,以字節為單位將數據壓入棧,從高到低按字節依次將數據存入ESP-1、ESP-2、ESP-3、ESP-4的地址單元。

      4) POP一個long型數據,過程與PUSH相反,依次將ESP-4、ESP-3、ESP-2、ESP-1從棧內彈出,放入一個32位寄存器。

      5) CALL指令用來調用一個函數或過程,此時,下一條指令地址會被壓入堆棧,以備返回時能恢復執行下條指令。

      6) RET指令用來從一個函數或過程返回,之前CALL保存的下條指令地址會從棧內彈出到EIP寄存器中,程序轉到CALL之前下條指令處執行

      7) ENTER是建立當前函數的棧框架,即相當于以下兩條指令:

      pushl %ebp

      movl %esp,%ebp

      8) LEAVE是釋放當前函數或者過程的棧框架,即相當于以下兩條指令:

      movl ebp esp

      popl ebp

      如果反匯編一個函數,很多時候會在函數進入和返回處,發現有類似如下形式的匯編語句:

      pushl %ebp ; ebp寄存器內容壓棧,即保存main函數的上級調用函數的棧基地址

      movl %esp,%ebp ; esp值賦給ebp,設置 main函數的棧基址

      ........... ; 以上兩條指令相當于 enter 0,0

      ...........

      leave ; 將ebp值賦給esp,pop先前棧內的上級函數棧的基地址給ebp,恢復原棧基址

      ret ; main函數返回,回到上級調用

      這些語句就是用來創建和釋放一個函數或者過程的棧框架的。

      原來編譯器會自動在函數入口和出口處插入創建和釋放棧框架的語句。

      函數被調用時:

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

      函數被調用時,返回時的EIP首先被壓入堆棧;創建棧框架時,上級函數棧的EBP被壓入堆棧,與EIP一道行成新函數棧框架的邊界

      2) EBP成為棧框架指針SFP,用來指示新函數棧的邊界

      棧框架建立后,EBP指向的棧的內容就是上一級函數棧的EBP,可以想象,通過EBP就可以把層層調用函數的棧都回朔遍歷一遍,調試器就是利用這個特性實現 backtrace功能的

      3) ESP總是作為棧指針指向棧頂,用來分配棧空間

      棧分配空間給函數局部變量時的語句通常就是給ESP減去一個常數值,例如,分配一個整型數據就是 ESP-4

      4) 函數的參數傳遞和局部變量訪問可以通過SFP即EBP來實現

      由于棧框架指針永遠指向當前函數的棧基地址,參數和局部變量訪問通常為如下形式:

      +8+xx(%ebp) ; 函數入口參數的的訪問

      -xx(%ebp) ; 函數局部變量訪問

      假如函數A調用函數B,函數B調用函數C ,則函數棧框架及調用關系如下圖所示:

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

      | EIP (上級函數返回地址) |

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

      +--> | EBP (上級函數的EBP) | --+ <------當前函數A的EBP (即SFP框架指針)

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

      | | Local Variables | |

      | | .......... | --+ <------ESP指向函數A新分配的局部變量,局部變量可以通過A的ebp-偏移量A訪問

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

      | r | Arg n(函數B的第n個參數) |

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

      | m | Arg .(函數B的第.個參數) |

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

      | | Arg 1(函數B的第1個參數) |

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

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

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

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

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

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

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

      | Local Variables | |

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

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

      | Arg n(函數C的第n個參數) | |

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

      | Arg .(函數C的第.個參數) | |

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

      | Arg 1(函數C的第1個參數) | |

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

      | Arg 0(函數C的第0個參數) | |

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

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

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

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

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

      | | Local Variables |

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

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

      frame of C

      圖 1-1

      再分析test1反匯編結果中剩余部分語句的含義:

      # mdb test1

      Loading modules: [ libc.so.1 ]

      > main::dis ; 反匯編main函數

      main: pushl %ebp

      main+1: movl %esp,%ebp ; 創建Stack Frame(棧框架)

      main+3: subl ,%esp ; 通過ESP-8來分配8字節堆棧空間

      main+6: andl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    xf0,%esp ; 使棧地址16字節對齊

      main+9: movl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    ,%eax ; 無意義

      main+0xe: subl %eax,%esp ; 無意義

      main+0x10: movl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    ,%eax ; 設置main函數返回值

      main+0x15: leave ; 撤銷Stack Frame(棧框架)

      main+0x16: ret ; main 函數返回

      >

      以下兩句似乎是沒有意義的,果真是這樣嗎?

      movl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    ,%eax

      subl %eax,%esp

      用gcc的O2級優化來重新編譯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反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    xf0,%esp

      main+9: xorl %eax,%eax ; 設置main返回值,使用xorl異或指令來使eax為0

      main+0xb: leave

      main+0xc: ret

      >

      新的反匯編結果比最初的結果要簡潔一些,果然之前被認為無用的語句被優化掉了,進一步驗證了之前的猜測。

      提示:編譯器產生的某些語句可能在程序實際語義上沒有用處,可以用優化選項去掉這些語句。

      問題:為什么用xorl來設置eax的值?

      注意到優化后的代碼中,eax返回值的設置由 movl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    ,%eax 變為 xorl %eax,%eax ,這是因為IA32指令中,xorl比movl有更高的運行速度。

      概念:Stack aligned 棧對齊

      那么,以下語句到底是和作用呢?

      subl ,%esp

      andl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    xf0,%esp ; 通過andl使低4位為0,保證棧地址16字節對齊

      表面來看,這條語句最直接的后果是使ESP的地址后4位為0,即16字節對齊,那么為什么這么做呢?

      原來,IA32 系列CPU的一些指令分別在4、8、16字節對齊時會有更快的運行速度,因此gcc編譯器為提高生成代碼在IA32上的運行速度,默認對產生的代碼進行16字節對齊

      andl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

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

      這里假設在進入main函數之前,棧是16字節對齊的話,那么,進入main函數后,EIP和EBP被壓入堆棧后,棧地址最末4位二進制位必定是1000,esp -8則恰好使后4位地址二進制位為0000。看來,這也是為保證棧16字節對齊的。

      如果查一下gcc的手冊,就會發現關于棧對齊的參數設置:

      -mpreferred-stack-boundary=n ; 希望棧按照2的n次的字節邊界對齊, n的取值范圍是2-12

      默認情況下,n是等于4的,也就是說,默認情況下,gcc是16字節對齊,以適應IA32大多數指令的要求。

      讓我們利用-mpreferred-stack-boundary=2來去除棧對齊指令:

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

      > main::dis

      main: pushl %ebp

      main+1: movl %esp,%ebp

      main+3: movl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    ,%eax

      main+8: leave

      main+9: ret

      >

      可以看到,棧對齊指令沒有了,因為,IA32的棧本身就是4字節對齊的,不需要用額外指令進行對齊。

      那么,棧框架指針SFP是不是必須的呢?

      # gcc -mpreferred-stack-boundary=2 -fomit-frame-pointer test1.c -o test

      > main::dis

      main: movl

    Linux下GDB反匯編和調試

    時間: 志藝942 分享

      Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。

      LINUX下GDB反匯編和調試

      1、 基本操作指令

      簡單的操作數類型說明,一般有三種,

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

    ,%eax

      main+5: ret

      >

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

      問題:去除SFP后有什么缺點呢?

      1)增加調式難度

      由于SFP在調試器backtrace的指令中被使用到,因此沒有SFP該調試指令就無法使用。

      2)降低匯編代碼可讀性

      函數參數和局部變量的訪問,在沒有ebp的情況下,都只能通過+xx(esp)的方式訪問,而很難區分兩種方式,降低了程序的可讀性。

      問題:去除SFP有什么優點呢?

      1)節省棧空間

      2)減少建立和撤銷棧框架的指令后,簡化了代碼

      3)使ebp空閑出來,使之作為通用寄存器使用,增加通用寄存器的數量

      4)以上3點使得程序運行速度更快

      概念:Calling Convention 調用約定和 ABI (Application Binary Interface) 應用程序二進制接口

      函數如何找到它的參數?

      函數如何返回結果?

      函數在哪里存放局部變量?

      那一個硬件寄存器是起始空間?

      那一個硬件寄存器必須預先保留?

      Calling Convention 調用約定對以上問題作出了規定。Calling Convention也是ABI的一部分。

      因此,遵守相同ABI規范的操作系統,使其相互間實現二進制代碼的互操作成為了可能。

      例如:由于Solaris、Linux都遵守System V的ABI,Solaris 10就提供了直接運行Linux二進制程序的功能。

      詳見文章:關注: Solaris 10的10大新變化

      3. 小結

      本文通過最簡的C程序,引入以下概念:

      SFP 棧框架指針

      Stack aligned 棧對齊

      Calling Convention 調用約定 和 ABI (Application Binary Interface) 應用程序二進制接口

      今后,將通過進一步的實驗,來深入了解這些概念。通過掌握這些概念,使在匯編級調試程序產生的core dump、掌握C語言高級調試技巧成為了可能。


    看了“LINUX下GDB反匯編和調試”還想看:

    1.編譯和調試的區別

    2.Ubuntu如何使用命令調節屏幕亮度

    3.Linux系統中如何調整swap大小

    4.Linux系統怎樣調整屏幕亮度

    5.Ubuntu下如何編輯開始菜單

    Linux下GDB反匯編和調試

    Linux下的匯編與Windows匯編最大的不同就是第一個操作數是原操作數,第二個是目的操作數,而Windows下卻是相反。接下來是小編為大家收集的LINUX下GDB反匯編和調試,希望能幫到大家。 LINUX下GDB反匯編和調試 1、 基本操作指令 簡單的操
    推薦度:
    點擊下載文檔文檔為doc格式
    2805004 主站蜘蛛池模板: 日本一区免费观看| 福利视频1000| 男女啪啪免费体验区| 扒开内裤直接进| 四虎影院最新域名| 中文字幕一区二区日产乱码| 蜜芽.768.忘忧草二区老狼| 日本理论片午午伦夜理片2021| 国产大片91精品免费观看男同 | 小信的干洗店1~4| 向日葵app下载视频免费| 中文字幕免费视频| 美国一级毛片免费| 成人片黄网站色大片免费| 四虎在线免费播放| 一本大道香焦在线视频| 福利在线小视频| 女人张开腿等男人桶免费视频| 免费大香伊蕉在人线国产| a级毛片免费高清毛片视频| 激情内射亚洲一区二区三区爱妻 | 特级毛片www| 天天干天天干天天| 亚洲日韩中文字幕天堂不卡| 手机在线看片你懂得| 日韩欧美色视频在线观看| 国产乱子伦农村xxxx| 中国娇小与黑人巨大交| 精品一区二区三区在线观看视频| 大陆三级午夜理伦三级三| 亚洲图片欧美另类| 91手机在线视频| 日本www高清视频| 免费扒开女人下面使劲桶| 91久久精品国产91久久性色tv| 欧洲成人爽视频在线观看| 国产国语高清在线视频二区| 丰满少妇人妻HD高清大乳在线| 精品国产综合区久久久久久| 在线亚洲人成电影网站色www| 亚洲人jizz日本人|