資源
題目:使用qemu執行並調試lab1中的軟件
為了熟悉使用qemu和gdb進行的調試工作,我們進行如下的小練習:
- 從CPU加電后執行的第一條指令開始,單步跟蹤BIOS的執行。
- 在初始化位置0x7c00設置實地址斷點,測試斷點正常。
- 從0x7c00開始跟蹤代碼運行,將單步跟蹤反匯編得到的代碼與bootasm.S和bootblock.asm進行比較。
- 自己找一個bootloader或內核中的代碼位置,設置斷點並進行測試
解答
問題1:從CPU加電后執行的第一條指令開始,單步跟蹤BIOS的執行
- tools/gdbinit的內容如下。可見,這里是對內核代碼進行調試,並且將斷點設置在內核代碼的入口地址,即kern_init函數
file bin/kernel
target remote :1234
break kern_init
continue
- 為了從CPU加電后執行的第一條指令開始調試,需要修改tools/gdbinit的內容為:
set architecture i8086
file bin/bootblock
target remote :1234
break start
continue
- 執行
make debug
,這時會彈出一個QEMU窗口和一個Terminal窗口,這是正常的,因為我們在makefile中定義了debug的操作正是啟動QEMU、啟動Terminal並在其中運行gdb。
debug: $(UCOREIMG)
$(V)$(QEMU) -S -s -parallel stdio -hda $< -serial null &
$(V)sleep 2
$(V)$(TERMINAL) -e "gdb -q -tui -x tools/gdbinit"
- Terminal窗口此時停在0x0000fff0的位置,這是eip寄存器的值,而cs寄存器的值為0xf000. (遇到一個問題:此時無法正確反匯編出代碼,使用x來查詢內存0xfff0處的值時顯示全0,不知道什么原因)
The target architecture is assumed to be i8086
0x0000fff0 in ?? ()
Breakpoint 1 at 0x7c00: file boot/bootasm.S, line 16.
-
輸入si,執行1步,程序會跳轉到0xe05b的地方。查看寄存器也可以發現eip的值變為0xe05b,而cs的值不變,仍然是0xf000.
-
反復輸入si,以單步執行。(由於BIOS中全是匯編代碼,看不懂其功能)。
問題2:在初始化位置0x7c00設置實地址斷點,測試斷點正常
-
我直接在tools/gdbinit中設置了斷點
break start
,由於boot loader的入口為start,其地址為0x7c00,因此這和break *0x7c00
效果是相同的。 -
設置斷點后,輸入continue或c,可以看到程序在0x7c00處停了下來,說明斷點設置成功。
問題3:從0x7c00開始, 將反匯編代碼與bootasm.S和bootblock.asm進行比較
- 反匯編的代碼與bootblock.asm基本相同,而與bootasm.S的差別在於:
- 反匯編的代碼中的指令不帶指示長度的后綴,而bootasm.S的指令則有。比如,反匯編 的代碼是
xor %eax, %eax
,而bootasm.S的代碼為xorw %ax, %ax
- 反匯編的代碼中的通用寄存器是32位(帶有e前綴),而bootasm.S的代碼中的通用寄存器是16位(不帶e前綴)。
- 反匯編的代碼中的指令不帶指示長度的后綴,而bootasm.S的指令則有。比如,反匯編 的代碼是
問題4:自己找一個bootloader或內核中的代碼位置,設置斷點並進行測試
這個比較簡單,不作記錄。