2015-01-10 46 views
1

這裏是我的代碼:我用gdb調試堆棧和堆棧幀有什麼區別?

17 mov  ebx,msg 
18 mov  edx,5 
19 push  ebx 

,這裏是輸出我有:

Breakpoint 1, print() at hello.asm:17 
(gdb) info register sp 
sp: 0xbffff37c 
(gdb) info stack 
#0 print() at hello.asm:17 

(gdb) step 
(gdb) info register sp 
sp: 0xbffff37c 
(gdb) info stack 
#0 print() at hello.asm:18 

(gdb) step 
(gdb) info register sp 
sp: 0xbffff378 
(gdb) info stack 
#0 print() at hello.asm:19 

很明顯嘛

push ebx 

'減' 的註冊sp由4字節..但是,當我輸入

info stack 

我仍然看到在hello.asm打印():19

我的問題是,什麼是信息堆棧顯示我的,什麼是我展示的信息登記藻?堆棧寄存器和信息堆棧之間的關係是什麼?

+0

您是否設立了賞金獎勵其中一個答案或您錯過信息?我的意思是,你已經得到了2個正確的答案,或者沒有?否則,你需要指定你還不明白的東西。 – Blechdose

+0

@Blechdose我不明白目前的答案。 –

+0

我認爲你的問題的一個問題是,標題是「堆棧和堆棧幀之間有什麼區別?」並且在問題中您實際上詢問了不同的事情。您詢問軟件gdb「info stack」和「info register esp」的2個命令之間有什麼區別。 – Blechdose

回答

1

當一個新的函數被調用時,一個新的堆棧幀被建立。每個堆棧幀代表一個功能。 在該堆棧框架內,當您將變量推入堆棧時,堆棧指針會隨着堆棧增長而發生變化,這是由於推送引起的。 print()hello.asm:19是gdb使用指令指針來顯示源代碼執行的地方。你在print()函數中,第19行,它是「push%ebx」 執行callq來調用另一個函數後,bt會告訴你當前的堆棧幀已經改變。

C-X A C-X 2 CRL-2

在gdb將終端分成3命令在底部疼痛,在中間窗格中拆卸,並且寄存器在頂部窗格。通過這種方式,您可以逐步瞭解您所處的位置以及寄存器狀態發生了什麼變化以及何時變化 - 哪些變化非常有用。

<咆哮> 直到它崩潰,因爲gdb的ncurses的接口(又名TUI)壞了,gdb的看門人不關心,不接受解決崩潰的補丁。如果它得到你太多,你需要使用gdb的前端,如Eclipse或洞察力可以給你同樣的信息,並可能不會崩潰,由於愚蠢的ncurses代碼< /咆哮>

1

info stackbacktrace的別名 - 它顯示了您所處的功能,只要它能夠確定它即可。

堆棧和esp寄存器無法在堆棧跟蹤中找到最深的位置 - 您當前正在執行的功能。要找到它,您需要檢查eip - 指向下一條要執行的指令。只有在此之後,您纔可以分析堆棧以查找您所在其他功能的返回地址。

+0

什麼是信息ESP特別顯示我? –

+0

它顯示了'esp'寄存器的內容 - 堆棧頂部的地址。 – zch

2

esp寄存器將指針保存到堆棧中。堆棧是特殊的內存區域,由c和C++編寫的應用程序使用它來存放函數的返回地址和局部變量。 當調試器想要確定函數調用鏈時,導致當前的進程指令 - 它通過查看位於堆棧中的返回地址鏈來實現。這可能導致你的困惑。所以,當前的指令!=堆棧。 基本上每次執行「調用」指令時,下一條指令的地址都會被放入堆棧,並且堆棧指針會減少,這樣當調用「返回」指令時,處理器就會知道返回的位置。

1

「堆棧」是運行時間使用你的應用程序主要有兩種用途的數據結構:

  1. 記錄有關調用的函數,這樣就可以調用子程序,並從他們回到他們在那裏叫。
  2. 將臨時局部變量存儲在特定於聲明它們的函數的上下文中。

你的CPU有一個特殊的寄存器,它的唯一目的是保持堆棧頂部的地址在內存中。這是「堆棧指針」,或sp。每個「push」將以sp減4(在32位模式下),並將值存儲在堆棧頂部,地址爲sp指示的地址。每個「pop」將做相反的處理,檢索堆棧頂部的值,然後將4加到sp

每次調用另一個函數時,附加信息都會存儲在堆棧中,包括返回地址(#1)和局部變量值(#2)。每個功能呼叫的信息都被稱爲「幀」。


info stack是一個GDB命令。它將「走」堆棧,尋找這些「堆棧幀」的邊界。從框架中,它將顯示與其關聯的功能等信息。這是足夠的智能,不一定關心在一個函數內的個人推動和流行;其目的是向您顯示調用函數順序的更高級別信息。


GDB中的step命令工作在源代碼行級別。通常,這是一行C代碼。但是,由於您正在使用匯編源代碼,因此每行對應於一條指令。

此外,由於您在彙編源代碼中工作,函數和堆棧框架的概念可能不適用!編譯-g將附加信息嵌入到二進制文件中,以幫助GDB與C函數匹配彙編指令以及有關局部變量的信息等。

我建議您首先編寫一個調用函數的簡單C程序,並執行有趣的東西。用-g進行編譯,並在GDB中逐步瀏覽。一旦熟悉這一點,調試彙編代碼可能會更容易。