一站式程式設計筆記(17,18,19)

2021-06-18 21:58:20 字數 1767 閱讀 8935

第17章:

彙編器把文字檔案轉換成目標檔案.o;目標檔案由若干個section組成,我們在匯程式設計序中宣告的.section會成為目標檔案中的section

然後鏈結器把目標檔案的section合併成幾個segment,生成可執行檔案。

最後載入器根據可執行檔案的segment資訊載入執行這個程式。

第18章:

函式呼叫解析:

在進入main()中,在呼叫的函式的時候,先把區域性變數和函式所需要的變數儲存起來,通過push壓棧來儲存。

注:其實在進入main中,ebp就已經被壓入堆疊了,以後要尋找變數都是依靠ebp來尋找的,因為esp是隨時變化的。

另外函式的引數都是從右到左壓入堆疊的,呼叫函式之後再把呼叫函式之後的下一條指令的位址壓入堆疊,然後執行call指令

然後修改eip的值,跳轉到呼叫函式執行。

在呼叫函式中:

先把ebp壓棧,注意,這裡是main函式的ebp。另外在這裡esp的值減了4(這步是自動完成),因為在push和pop中esp是根據此來變化的。

然後把esp的值給ebp,那麼這個函式的ebp值也已經儲存了。

我的理解是:ebp和esp是一一對應的,在設定好ebp值後,你mov %esp就是往堆疊中儲存資料了,相當於push。並且呼叫函式的ebp的值才需要push,而本函式的ebp 需要賦值就好,不需要壓棧!

返回的時候就是個逆過程,把ebp的值給esp,然後通過ret指令,esp值增加4。回到了main函式。

const唯讀的,一旦確定不能修改,並且一定要初始化;

棧是從高位址向低位址增長,但陣列卻是從低向高排列。

register 並沒有在棧上分配空間,而是直接在ebx寄存。

結構體內存布局:

棧是從高位址向低位址增長的,但是結構體成員卻是低位址向高位址排列的。和陣列不同的是,結構體成員並不是乙個接乙個的,中間有空隙,稱為填充。是因為編譯器在考慮在安排各種變數的位址時會考慮到對齊問題。(即指令的起始位址應該是4或者2的整數倍);

不懂的是為什麼編譯器要這麼存放陣列和結構體呢?是出於什麼原因考慮的。。。

聯合體:乙個聯合體的各個成員占用相同的記憶體,聯合體的長度等於其中最長成員的長度。至於在記憶體中時如何存放的呢,其實這個無關緊要,因為我們如果看成是位元,或者看成是位元組都可以的。就是說我們看聯合體成員,可以換一種視角,來知道記憶體的布局;

第19章:

主函式中包含「*.h」是因為.h檔案包含了其他.c檔案定義的函式,這裡只是將這些預設的鏈結屬性為extern的函式組合在一起,放到.h檔案中,然後給main.c檔案來用。 這裡為什麼要這麼組織呢?

是因為.h檔案只是宣告,並不是定義。 而如果main和foo都包括stack.c的時候,還有乙個函式想將main.c和foo.c鏈結在一起的時候就不好辦了。因為不能重複定義,但是可以重複宣告。

靜態庫:把一組**編譯成乙個庫,可以用自定義的**組成;

組成靜態庫需要用到ar打包命令,靜態庫以.a作為字尾。

編譯器在鏈結時,先找共享庫另外再去尋找靜態庫。如果只考慮靜態庫,可以指定-static選項。

要檢視是不是鏈結時用到了靜態還是其他,可以用objdump -d main 將可執行檔案反彙編成彙編檔案,然後檢視相應的彙編檔案。

共享庫: 

組成共享庫時在編譯的時候需要加-fpic.這個共享庫一般出現在c語言的庫檔案中!

共享庫(動態)時是只確定位址,在執行時才做動態鏈結; 而靜態鏈結庫時,鏈結器會把靜態庫中的目標檔案取出和真正的可執行檔案真正的鏈結在一起。

我們一般用的庫就是靜態庫,這樣不需要的目標檔案其實是不需要做鏈結的。這樣的另乙個好處是鏈結時只要寫乙個庫檔名。

Linux C程式設計一站式學習 筆記

關於程式的討論裡提到了c語言的可移植,原本不知道為什麼,現在知道,原來是因為各種平台上都有c語言的編譯器,這就好像是一種由於廣泛使用而成為規範的東西一樣,當所有機器上都有你的編譯器的時候,你的可移植性當然強了。之前看v6shell的 就沒明白詞法和語法有什麼差別,這裡講到了詞法就是單詞 token ...

Linux C程式設計一站式學習 筆記

1變數宣告與函式宣告有一點不同,函式宣告的extern關鍵字可以省略,而變數宣告不寫extern意思完全不同,表示為定義了乙個區域性變數。2static關鍵字宣告具有internal linkage,這些函式變數作用域僅限本檔案,則不想被外部檔案所訪問的變數和函式就可以宣告為static。3用角括號...

Linux C程式設計一站式學習

北京亞嵌教育研究中心 ps ef grep sctp grep全稱是global regular expression print,表示全域性正規表示式.gdb除錯又看一遍。迅速用起 pthread cond timedwait 條件變數是利用執行緒間共享的全域性變數進行同步的一種機制,主要包括兩個...