彙編與棧幀學習(一)

2022-06-22 03:24:08 字數 1828 閱讀 3605

最近學習《深入理解計算機系統》,書中全是彙編,正好藉著gdb來研究一下組合語言和函式呼叫時棧幀的變化。於是寫下這個開篇的部落格,我先以乙個簡單的程式進行研究:

如上圖這個程式(func.c)含有兩個函式。main和add,功能很簡單就是求兩個兩個數的和然後輸出。

用命令:gcc func.c -o func.o 編譯成目標檔案func.o。用gdb載入:

首先在main和add兩處設定了斷點。為了便於觀察程式執行時棧幀的變化。之後執行程式,對main進行反彙編看一下main的匯程式設計序。

如上所示,斷點在位址0x08048436停住了(這行沒有執行),可以看出載入進來執行後已經執行了兩條指令。即將ebp壓棧,令ebp 和 esp指向同乙個記憶體。

這時可以看一下在ebp中的值是0xbffff0e8,和棧幀的一些資訊。

輸入了3次ni命令(ni命令是每次執行乙個語句),所以這時程式執行到了0x08048444停住了。因為需要儲存一些引數,所以程式分配了32位元組來分配空間,然後將在main函式裡的兩個值傳入到分配好的空間中。即將10 和 8 分別存入0x4(esp),即這個引數10儲存在記憶體位址為0xbffff0c4裡和0x8(esp)處(8存在記憶體位址為0xbffff0c8裡)

同理。一次執行一條指令。執行了兩次進入了add函式的棧幀。以此同時在這個棧幀裡已經把空間分配好了。在0x08048423處指令表示分配16個位元組這個函式使用。

上圖是兩次ebp和esp的變化。上邊是main棧幀下面是add棧幀。之後繼續逐條執行程式產生下面的結果:

通過讀這個匯程式設計序。第四條看出將0xc(%ebp)裡的值存入暫存器%eax中。通過計算可以知道0xc(%ebp)的位址就是0xbffff0c4。即我們在main棧幀中存放引數10的位址,也就是將10存入eax暫存器中。同理將8存放到edx暫存器中。對兩個暫存器相加存入eax,同時將結果存入0xbffff0b4中。返回。

如上圖。返回後,在main棧幀中繼續執行。來到了0x08048450處,這時ebp和esp值有恢復成了main棧幀中的值。繼續執行程式。執行完後會有如下結果:

上邊的程式看到將結果存入到0x1c(%esp)處的記憶體處,然後呼叫printf的庫函式,進行輸出結果。結束。

棧幀 組合語言詳解

原來我以為在c語言中指標已經是非常麻煩了,沒想到棧幀給我甜蜜一擊,但最後一路學習下來也不是多麼麻煩的事。首先我們得明確為什麼有函式,其作用是 在面向過程語言的重要組成成分,它將具有相同功能的語句組合到一塊,便於我們使用,提高程式可讀性,減少 量。以main函式為例,在使用過程中首先呼叫 tmainc...

棧操作與棧幀

結構化程式的乙個最基本的單元就是 函式 或者叫 過程 在彙編這一層自然也相應的有支援這些概念的指令操作,如棧操作和棧幀的概念。1 定址方式 我們已經知道在運算元表示中有一種是用來指示記憶體位址的內容的,在gnu assembly中指示記憶體位址有多種方式,這些方式被統稱 定址方式 通用的定址格式為 ...

函式棧幀(用彙編來剖析)

好久沒寫部落格了,學校開始實習,找了乙個極破的地方,站公交將近兩個小時,一天來回就要死了,說是實習,就是變著樣的培訓,一點實習的意思都沒有,辣雞。因為位址空間內的棧是從高位址向低位址生長的,也就是說壓棧順序靠後的反而位址比較低,棧底的位址高於棧頂的位址,下面貼上一段測試 1 include2 3 i...