ucore-lab1-练习5report
實驗5--實現函數調用堆棧跟蹤函數
需要完成kdebug.c中函數print_stackframe的實現,可以通過函數print_stackframe來跟蹤函數調用堆棧中記錄的返回地址。
一.函數堆棧
主要的兩點在于棧的結構和ebp寄存器的作用。一個函數調用動作可分解為:零到多個PUSH指令(用于參數入棧),一個CALL指令。CALL指令內部其實還暗含了一個將返回地址(即CALL指令下一條指令的地址)壓棧的動作(由硬件完成)。幾乎所有本地編譯器都會在每個函數體之前插入類似如下的匯編指令:
?
這樣在程序執行到一個函數的實際命令前,已經有以下數據順序入棧:參數,返回地址,ebp寄存器。
函數調用的步驟:
1.參數入棧:將參數從右向左依次壓入棧中。 ?
?? ? 2. 返回地址入棧:call指令內部隱含的動作,將call的下一條指令入棧,由硬件?? ??? 完成。 ?
?? ? 3. 代碼區跳轉:跳轉到被調用函數入口處。 ?
?? ? 4. 函數入口處前兩條指令,為本地編譯器自動插入的指令,即將ebp寄存器入棧,?? ??? 然后將棧頂指針esp賦值給ebp。
相反的,函數返回的步驟為:
1.保存返回值,通常將函數返回值保存到寄存器EAX中。 ?
?? ? 2. 將當前的ebp賦給esp。 ?
?? ? 3. 從棧中彈出一個值給ebp。 ?
?? ? 4. 彈出返回地址,從返回地址處繼續執行。
并且在函數調用過程中的ebp起著關鍵作用,從該地址向上(棧底方向)能依次獲取返回地址、參數值,向下(棧頂方向)能獲取函數局部變量值,而該地址處又存儲著上一層函數調用時的ebp的值,于是以此為線索可以形成遞歸,直至到達棧底。這就是函數調用棧。
?
二.print_stackframe函數的實現
由以上知識和源代碼文件中的注釋實現print_stackframe():
?
執行’make qemu’指令得到的結果為:
?
可以觀察到顯示結果與實驗指導書上一致。對于最后一行:其對應的是第一個調用堆棧的函數,即bootmain.c中的bootmain函數,因為bootloader設置的堆棧從0x7c00開始,執行’call bootmain’轉入bootmain函數。其ebp=0x00007bf8,此時的eip=0x00007d6e,其壓入的4個參數分別為0xc031fcfa, 0xc08ed88e, 0x64e4d08e, 0xfa7502a8。
?
?
轉載于:https://www.cnblogs.com/FrankChen831X/p/10733836.html
總結
以上是生活随笔為你收集整理的ucore-lab1-练习5report的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux进程分配内存的两种方式--br
- 下一篇: 天眼查如何查自己名下的公司