工作學習筆記——CSAPP第三章

  最近在讀《深入理解計算機系統》(CSAPP)的第三章——程序的機器語言表示。之前這塊內容也有所接觸,對書中提到的一些細節問題倒更感興趣一些。


一、可變長數組  

  剛開始學習C語言時,都會被教到,聲明數組時,數組的維數只能使用常量,也就是隻能聲明定長數組。如果數據個數不定的話,就要使用malloc動態分配。當時只是死記硬背,並沒有想想這是什麼道理。工作中瞭解到,函數中聲明的數組一般存儲在棧上,數組元素通過棧指針加偏移量和下標偏移來訪問。那時就已經有些困惑,棧上空間的分配只是將sp寄存器減一個數,如果這個數是存儲在寄存器或者內存中的話,不是就可以做到聲明函數上的變長數組了麼?C庫中有一個函數alloca,與malloc的區別就是,申請的內存是分配在棧上的,這個不也意味着棧上的變長數組是可能的?

  c數組維數不支持變量這種說法,可能是c編譯器初期爲降低編譯器設計難度而採取的一種限制。CSAPP中提到,C99標準已經明確定義了變長數組,新的gcc編譯器也實現了這塊內容,我們已經可以寫這樣的語句了

  int arrary[m][n];

  不過這種數組只能在函數內部使用,如果傳遞到函數外的話,結果可能是災難性的。因爲函數一退出,給函數分配的變量棧空間也隨之銷燬了。另外,即使是VC2010,也不支持c99的這種定義。


二、棧幀寄存器ebp是否必要

  在一些介紹函數調用棧的文章中,經常會提到棧幀寄存器ebp,它的值其實就是函數剛剛調用時的esp的值。函數執行過程中,使用ebp加偏移量來對參數、函數局部變量進行訪問。調試時也可以根據ebp的值還原出當前函數調用棧。不直接使用esp的原因,一是函數執行過程中esp值可能發生變化,一是方便調試。但是函數執行過程中,esp的值何時變化總是沒想清楚,調用子函數不必說,子函數退出時自然會恢復esp。難道是編譯器會在函數執行過程中隨時分配變量,就像C++那樣在函數中間聲明變量?從CSAPP對x86-64的介紹來看,這可能又是一個編譯器爲降低實現難度而採取的策略,因爲x86-64程序中,rbp已經作爲通用寄存器使用,函數調用過程中不再設專門的棧幀寄存器。並且函數使用的空間統一在函數調用開始出分配,調用過程中esp不再變化。通過網上查找到的資料來看,不使用棧幀寄存器的程序也是可以支持調試的。其實即使是x86,gcc也早就有個選項,好像叫做no-stack-frame-point,來指明程序不使用棧幀寄存器。


三、x86、x86-64

Intel設計的x86,AMD學過來用。Intel自家的IA64,市場不歡迎。反倒是AMD在x86基礎上設計的x86-64流行起來,搞得Intel又反過來學。這段歷史也很有趣。

發佈了56 篇原創文章 · 獲贊 26 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章