Linux核心分析-1:電腦程式的一生

來源:互聯網
上載者:User

標籤:

首先,組裝過電腦的童鞋應該知道,電腦是由CPU,記憶體,硬碟,主板,電源組成的,當然,玩遊戲的童鞋還會念念不忘顯卡(比如GTX980戰術核顯卡)

只要有了這些東西,電腦就可以跑起來了。

然而這些東西又是如何協同工作而讓程式啟動並執行呢?

首先,我們得知道一個叫做作業系統的東西,本質上,它也是一個程式,抽象上,它可以被看作成一個環境。這個環境保證了各個程式可以正常工作,正常休息,正常學習(喂,這就不正常了吧!)

而我們程式員只要用標準的文法來告訴作業系統我們要電腦做什麼工作就可以了,比如,這裡有一段C語言代碼:

  1. int g(int x)
  2. {
  3.   return x + 3;
  4. }
  5.    
  6. int f(int x)
  7. {
  8.   return g(x);
  9. }
  10.    
  11. int main(void)
  12. {
  13.   return f(8) + 1;
  14. }

 

這個程式在電腦上是如何工作的呢?我們對其進行反組譯碼,得到彙編代碼:

化簡之後:

g:    

    pushl    %ebp

    movl    %esp, %ebp

    movl    8(%ebp), %eax

    addl    $3, %eax

    popl    %ebp

    ret

f:

    pushl    %ebp

    movl    %esp, %ebp

    subl    $4, %esp

    movl    8(%ebp), %eax

    movl    %eax, (%esp)

    call    g

    leave

    ret

main:

    pushl    %ebp

    movl    %esp, %ebp

    subl    $4, %esp

    movl    $8, (%esp)

    call    f

    addl    $1, %eax

    leave

    ret

 

我們首先來看到Main函數進入點的兩條彙編代碼:

Pushl %ebp

Movl %esp,%ebp

Pushl指令是把ebp寄存器的值壓在棧上,把這個值給儲存起來,而movl指令則是把esp上的值放在了ebp,使ebp得到了一個新的值,這個新的值等於esp的值。

所以我們知道esp和ebp一開始都相等,也就是說以此就建立了一個程式的隔離儲存區 (Isolated Storage)堆棧(PS:我們可以把ebp看成堆棧的開始,esp看成堆棧的末尾,esp增長,則代表棧增長,反之則減少)

 

通俗一點來說,就是ebp和esp他們決定開一個新坑。。。

好了,開了新坑以後,就要填坑了,後面的C代碼調用了函數f(8),與之對應的是後面的三條彙編代碼:

Subl $4,%esp

Movl $8,(%esp)

Call f

首先,電腦把傳入的參數8壓到了棧上面,要完成這項操作,首先必須先擴充一下棧空間,就像前面提到的,使esp增長,怎麼增長呢,首先讓esp寄存器指向的地址減去4,再把8填到這個擴充的空間中。

之後,調用Call,也就是調用f函數,Call這句話相當於儲存現在的上下文然後改變eip指向的地址(要執行的程式碼片段的位置改變了)。

於是eip的當前地址被壓到了棧中,然後eip的地址就指向了函數f,函數f又做了和main函數開始部分相同的工作,通俗來說,它也開闢了一個獨立堆棧儲存空間(新坑),於是乎,函數f也坐起了浩浩蕩蕩的填坑工作。

在C語言中,我們看到f函數調用了g函數,與main函數調用f函數類似,首先電腦擴充了棧空間,然後把x壓入到推棧中,但是與上一個不同的是電腦並沒有直接把堆棧中的值壓到堆棧中,而是靠eax寄存器做了一次中轉:

movl    8(%ebp), %eax

movl    %eax, (%esp)

雖然過程不同,但結果一樣,之後調用Call,eip再一次跳轉到g函數那裡,開新坑還有填坑:

pushl    %ebp

movl    %esp, %ebp

movl    8(%ebp), %eax

addl    $3, %eax

我們從第三條彙編代碼開始,也就是將f函數傳給g的參數x取出並放在了eax寄存器上,第四條addl語句執行了x+3

之後popl %ebp,也就是把棧頂的值彈到ebp上,我們知道ebp是棧的開始,ebp的值改變也就意味著跳轉到了一個新的棧上。

而這個新的棧正是函數f的隔離儲存區 (Isolated Storage)堆棧。

Ret語句相當於彈出棧頂的數值到eip上,而這個彈出的值正是函數f調用g函數之後的地址。

於是程式又回到了函數f中,並得到了傳回值(存在了eax寄存器中):

Leave

這條語句代表的含義是

movl    %esp,     %ebp

popl    %ebp

返回到上一個隔離儲存區 (Isolated Storage)堆棧中。

Ret之後eip又指向main函數調用f函數的下一行代碼。也就是x+1,由於eax負責儲存返回後的函數的結果,所以有:

Addl $1,%eax

之後main函數返回,之後啊。。我編不下了。。。

電腦的工作,也可以說是作業系統的工作就是不斷地執行一個迴圈,這個迴圈儲存上一個迴圈的上下文,資料,然後為當前迴圈開闢一個上下文和儲存空間,讓當前的迴圈做事,如果當前迴圈又開始一個新的迴圈那麼就會重複這項工作,如果這項迴圈完成了,並沒有開啟新的迴圈,電腦就跳轉到上一個迴圈上去。如果用一個輪子比喻會比較貼切一些,這個輪子既可以往前轉也可以向後轉。

不過,我更喜歡電腦程式的構造與解釋所闡述的,程式員就像一個魔法師,他們寫出符文來變出各種各樣的魔法,而電腦就是一個可以實現無限夢想的魔杖。

blackerXHunter

原創作品轉載請註明出處

《Linux核心分析》MOOC課程,http://mooc.istudy.163.com/course/USTC-1000029000

Linux核心分析-1:電腦程式的一生

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.