通過反組譯碼一個簡單的C程式,分析彙編代碼理解電腦是如何工作的

來源:互聯網
上載者:User

標籤:馮諾依曼   彙編   編譯器   

劉子健 原創作品轉載請註明出處《Linux核心分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000




對一下代碼進行反組譯碼分析:

int g(int x){  return x + 42;} int f(int x){  return g(x);} int main(void){  return f(42) + 42;}


我的主機是64位的Linux,所以使用的反組譯碼代碼也是64-bits的.

.file"2015_03_01.c".text.globlg.typeg, @functiong:.LFB0:.cfi_startprocpushq%rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq%rsp, %rbp.cfi_def_cfa_register 6movl%edi, -4(%rbp)movl-4(%rbp), %eaxaddl$42, %eaxpopq%rbp.cfi_def_cfa 7, 8ret.cfi_endproc.LFE0:.sizeg, .-g.globlf.typef, @functionf:.LFB1:.cfi_startprocpushq%rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq%rsp, %rbp.cfi_def_cfa_register 6subq$8, %rspmovl%edi, -4(%rbp)movl-4(%rbp), %eaxmovl%eax, %edicallgleave.cfi_def_cfa 7, 8ret.cfi_endproc.LFE1:.sizef, .-f.globlmain.typemain, @functionmain:.LFB2:.cfi_startprocpushq%rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq%rsp, %rbp.cfi_def_cfa_register 6movl$42, %edicallfaddl$42, %eaxpopq%rbp.cfi_def_cfa 7, 8ret.cfi_endproc.LFE2:.sizemain, .-main.ident"GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"

反組譯碼得到的代碼裡面有很多提示資訊,提示資訊以 . 開頭,程式執行時這些提示資訊不是指令,我們在這個反組譯碼範例裡面可以精簡代碼,把這些提示資訊刪除.有些資訊不能剔除,這些資訊是編譯器必須的,否則你過不了編譯連結.

下面是精簡後的反組譯碼代碼:以下代碼可以通過 gcc ./2015_03_01.s -o ./a.out

.text.globlg.typeg, @functiong:pushq%rbpmovq%rsp, %rbpmovl%edi, -4(%rbp)movl-4(%rbp), %eaxaddl$42, %eaxpopq%rbpret.sizeg, .-g.globlf.typef, @functionf:pushq%rbpmovq%rsp, %rbpsubq$8, %rspmovl%edi, -4(%rbp)movl-4(%rbp), %eaxmovl%eax, %edicallgleaveret.sizef, .-f.globlmain.typemain, @functionmain:pushq%rbpmovq%rsp, %rbpmovl$42, %edicallfaddl$42, %eaxpopq%rbpret.sizemain, .-main



關於基本彙編指令的分析,我之前有筆記,可以去看這裡:

http://blog.csdn.net/cinmyheart/article/details/25558911

我們這裡著重分析反組譯碼代碼:

g: , f:, main: 均用來指示函數的入口.

對於函數main.

首先壓棧,pushq 指令將rsp寄存器的值減去一個指標長度,在64-bits機器上即8byte,然後將 rbp寄存器的值寫入到rsp指向的地址處.

movq %rsp, %ebp指令則將rsp寄存器的值賦值給rbp寄存器.這樣一來,屬於main函數的棧地區便構建好了.

接著movl 把立即數42賦值給寄存器edi, 然後call指令調用函數f.函數f的返回值會儲存在eax寄存器中,等待f調用完之後,會把eax寄存器的值和立即數42相加,並儲存在eax寄存器中.最後把rbp寄存器處的值彈棧.然後ret指令返回.

---------------------------------------------------------------------------------

call  f 

指令就相當於

push %eip #把當前指令指標寄存器壓棧,然後跳轉到f處
jump f

---------------------------------------------------------------------------------

ret 指令就相當於

popl %eip  #把當前esp寄存器指向地址處的值,賦值給eip

然後把esp寄存器的值減去一個指標長度,即8-byte

---------------------------------------------------------------------------------



看看函數f都幹了神馬.

還是和上面介紹main函數一樣的"老規矩",構建函數f的堆棧,

pushq %rbp

movq %rsp, %rbp

接著使用subq $8, %rsp把rsp寄存器的值減去8.

接著把edi寄存器的值賦值給rbp寄存器指向地址處減去4byte的地址處

緊接著,把這個地址處的值賦值給eax寄存器.

把eax寄存器的值又賦值給edi寄存器(其實我想說,這不是嚇折騰麼...這編譯器啊..這期間edi寄存器的值沒變)



然後調用函數g

一句話概括就是把edi寄存器的值加上42賦值給eax寄存器,然後返回.(不改變edi寄存器的值)




闡明自己對“電腦是如何工作的”理解:

對於正常化後的程式指令,逐一的對程式指令進行"解釋處理".不同的CPU,可能有不同的彙編指令集,比方說Intel -- X86 /X64平台,ARM平台,PowerPC等等,但是他們最基本的的思想都是近似的--馮諾依曼體繫結構.

數字電腦的數制採用二進位;電腦應該按照程式順序執行


-----------------------






通過反組譯碼一個簡單的C程式,分析彙編代碼理解電腦是如何工作的

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.