前面我們已經搭建好了bochs的環境,並且將我們的匯編程序寫入了硬盤里面,現在我們來看看如何通過bochs來調試我們的程序。
前文:https://www.cnblogs.com/Sna1lGo/p/15695712.html
bochs安裝文件夾
安裝完bochs后,在安裝目錄下我們可以看到有兩個.exe可執行程序:
bochs.exe就和正常的安裝的虛擬機一樣了,就是直接運行了。
而bochsdbg.exe才是我們要的可調試的虛擬機。
同時可以看到這個文件夾下面有一個docs文件夾,里面包含了bocsh的一些手冊,感興趣的可以讀一下。
進行bochsdbg調試:
首先要啟動bochsdbg虛擬機:
然后得添加配置文件,前面的章節我們是添加了配置的,但是如果你沒保存,那么很不幸你得再來一次了,需要注意的是保存的配置文件千萬不要修改配置文件的名字。這里由於我保存了的我就直接start了。
加載后是這樣一個界面:
左邊的display就類似於顯示器了,然后右邊的就是命令行調試窗口,啟動后命令行調試窗口前面顯示的是一系列虛擬機的狀態信息。
bochs會在執行第一條指令的時候停下來,等待我們的操作,也就是這里的命令行調試界面:
bochs的調試指令可以看bochs的官方文檔上看到:
當然它也包含在了我們安裝bochs文件夾的docs文件夾下面。
Next at t=0
(0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b ; ea5be000f0
0x0000fffffff0 代表真實的物理地址
f000:fff0 是邏輯地址
jmpf 0xf000:e05b 是匯編指令
ea5be000f0 是機器指令
Next at t=0 中的t是執行的指令個數,也叫做內部時鍾
注:細心的朋友可能會發現,這里的f000:fff0的邏輯運算是無法計算得到0x0000fffffff0地址的,這個只會在處理器剛啟動的時候發生,然后后面會解釋,這里先暫時就這個樣子。
肯定有同學會奇怪啊,前面我們說了8086啟動的第一條指令是jmp FFFF:0000啊,這里怎么不一樣,那說明這個cpu不是8086呀。哈哈。
我們把這個調試界面往前翻一下,查看前面的狀態信息可以看到:
這里的CPU configuration也就是CPU的配置信息是x86-64的,是intel的支持x86的CPU並不是8086CPU。
這里我們可以先單步執行看看內容,這里是所有的執行指令:
c continue executing
cont
continue
s [count] execute count instructions, default is 1
step [count]
s [cpu] [count] for SMP simulation, execute count instructions on cpu, default is 1
step [cpu] [count]
s all [count] for SMP simulation, execute count instructions on all cpus
step all [count]
Ctrl-C stop execution, and return to command line prompt
Ctrl-D if at empty line on command line, exit
q quit debugger and execution
quit
exit
可以采用s來單步執行,默認是只執行一條,就到了這里:
可以看到這個地址區域,是滿足前面我們將的cpu地址分區的BIOS地址區域的在F0000~FFFFF之間。
那么如果我們想直接到我們寫的主引導扇區里面怎么辦呢,我們可以給主引導扇區的第一條代碼打一個斷點,這里是所有的斷點指令:
NOTE: The format of 'seg', 'off', and 'addr' in these descriptions,
are as follows. I don't have any way to set the current radix.
hexidecimal: 0xcdef0123
decimal: 123456789
octal: 01234567
vbreak seg:off Set a virtual address instruction breakpoint
vb seg:off
vbreak seg:off if "expr" Set a conditional virtual address instruction breakpoint
vb seg:off if "expr"
lbreak addr Set a linear address instruction breakpoint
lb addr
lbreak addr if "expr" Set a conditional linear address instruction breakpoint
lb addr if "expr"
pbreak [*] addr Set a physical address instruction breakpoint
pb [*] addr (the '*' is optional for GDB compatibility)
break [*] addr
b [*] addr
pbreak [*] addr if "expr" Set a conditional physical address instruction breakpoint
pb [*] addr if "expr" (the '*' is optional for GDB compatibility)
break [*] addr if "expr"
b [*] addr if "expr"
info break Display state of all current breakpoints
bpe n Enable a breakpoint
bpd n Disable a breakpoint
delete n Delete a breakpoint
del n
d n
那么打斷點肯定是不能像vs調試一樣直接給代碼打上斷點然后直接調試就完事了,在cpu的層面是直接給地址打斷點,執行到該處就直接停下來。前面的博客我們學習到,CPU會把主引導扇區的內容加載到內存的 0000:7c00處,那么我們直接給這個地址打個斷點然后運行到這個地址就停下來不就行了嗎。

b 0x7c00
解釋一下這條命令,上面我寫了所有的斷點指令,然后單獨的 b 后面是跟着addr,然后邏輯地址的0000:7c00就是物理地址的 7c00,所以我這樣使用是沒問題的。
然后我們可以輸入執行指令,來直接執行到設置的斷點處:
這里就是我們前面寫好的匯編代碼了。
然后采用s指令單步調試來把我們的代碼都執行完:
好這里就執行完了,然后可以查看一下寄存器,看看ax,dx是不是我們設想的內容。
以下是查看bochs虛擬機信息的所有指令:
r|reg|regs|registers List of CPU integer registers and their contents
fp|fpu List of all FPU registers and their contents
mmx List of all MMX registers and their contents
sse|xmm List of all SSE registers and their contents
ymm List of all AVX registers and their contents
sreg Show segment registers and their contents
dreg Show debug registers and their contents
creg Show control registers and their contents
info cpu List of all CPU registers and their contents
info eflags Show decoded EFLAGS register
info break Information about current breakpoint status
info tab Show paging address translation
info device Show state of the specified device
可以看到ax和dx確實是我們想要的內容,0x00F0和0x00c0。
這樣就很完美了。
由於我們這次寫的匯編代碼很簡單,所以就這么幾條就執行完了。
可以使用退出指令來直接退出該bochs虛擬機了:
q quit debugger and execution
quit
exit
這樣摁完Enter回車就可以美美噠結束了。
小結
采用原原本本的通過cpu來執行匯編代碼的方式雖然比較繁瑣,但是逼格很高,哈哈,至少我是這樣認為的。
總結一下流程: