8086匯編開發(fā)環(huán)境搭建和Debug模式介紹(圖文詳解)
1. 8086匯編開發(fā)環(huán)境搭建
在上篇博客中簡(jiǎn)單的介紹了8086匯編語言。工欲善其事,必先利其器,在8086匯編語言正式開始學(xué)習(xí)之前,先介紹一下如何搭建8086匯編的開發(fā)環(huán)境。
匯編語言設(shè)計(jì)之初是用于在沒有操作系統(tǒng)的裸機(jī)上直接操作硬件的,但對(duì)于大部分人來說,在8086裸機(jī)上直接進(jìn)行編程將會(huì)面臨各種困難。好在我們可以使用軟件模擬器來模擬硬件進(jìn)行8086的學(xué)習(xí)實(shí)踐。在《匯編語言》中作者推薦通過windows環(huán)境下的masm和debug進(jìn)行學(xué)習(xí)。
masm介紹:
masm是一款DOS下的匯編工具包,在8086匯編的學(xué)習(xí)中我們需要其中的幾個(gè)文件,分別是masm.exe,link.exe。
masm.exe匯編器,用于將文本格式的匯編語言源文件編譯為.obj結(jié)尾的二進(jìn)制文件,其生成的.obj結(jié)尾的二進(jìn)制目標(biāo)文件是被編譯的源文件的對(duì)應(yīng)的機(jī)器碼。單獨(dú)的源程序目標(biāo)文件通常是無法直接運(yùn)行的,還需要和互相依賴的其它同樣編譯完成的二進(jìn)制文件鏈接在一起才能生成最終的可執(zhí)行文件(比如所需要的靜態(tài)庫(kù)函數(shù))。因此,obj文件通常也被叫做中間文件。
link.exe鏈接器,obj文件需要通過鏈接才能轉(zhuǎn)換成可執(zhí)行程序,而鏈接器就是負(fù)責(zé)完成這一任務(wù)的。鏈接器能將多個(gè)obj目標(biāo)文件以及其所依賴的庫(kù)程序進(jìn)行統(tǒng)一處理(例如多個(gè)目標(biāo)文件中指令、數(shù)據(jù)內(nèi)存地址的偏移處理),并生成可執(zhí)行文件。
debug介紹:
debug.exe調(diào)試器,windows提供了一個(gè)在dos中調(diào)試8086匯編程序的工具debug.exe,提供了展示程序運(yùn)行時(shí)CPU中各寄存器、內(nèi)存中數(shù)據(jù),指令級(jí)的單步調(diào)試等功能。debug程序的使用會(huì)在本篇博客的后半段進(jìn)行詳細(xì)介紹。
64位操作系統(tǒng)兼容性問題:
由于《匯編語言》一書出版較早,當(dāng)時(shí)的windows系統(tǒng)還是32位的,32位windows系統(tǒng)都默認(rèn)安裝了masm與debug,能打開dos窗口直接使用。但目前普遍使用的、新的windows 64位操作系統(tǒng)中卻并沒有默認(rèn)提供masm工具包和debug.exe,同時(shí)masm、debug也與64位的windows系統(tǒng)版本不兼容。
想在64位的windows系統(tǒng)下使用masm、debug有兩個(gè)常用方法:
1. 通過虛擬機(jī)安裝一個(gè)老版本的windows操作系統(tǒng)(推薦windows xp)
2. 通過DOSBox這一輕量級(jí)的ms-dos模擬器來運(yùn)行,但上文所述的依賴程序需單獨(dú)下載(百度網(wǎng)盤下載鏈接:
鏈接: https://pan.baidu.com/s/1JlOEFoV7h37Z_NY7NKc-gw
提取碼: x3ai
個(gè)人推薦第二種方法,下面介紹如何在windows64位操作系統(tǒng)下使用DOSBox來搭建8086匯編語言的開發(fā)環(huán)境。
DOSBox安裝與使用
DOSBox下載安裝:
DOSBox可以在官網(wǎng)下載,這里也提供了百度網(wǎng)盤的下載鏈接(0.74版本):
鏈接: https://pan.baidu.com/s/1W3f6_jsSK4HrHWDO_IfqRg
提取碼: 7ugx
安裝完畢后,找到安裝目錄下的DOSBox.exe并啟動(dòng),能看到如下圖界面。

作為dos的模擬器和普通的dos窗口沒有明顯區(qū)別,但是初始時(shí)并不能直接訪問到本地磁盤,需要先將本地磁盤掛載到DOSBox中。
DOSBox掛載本地磁盤:
1. 在本地操作系統(tǒng)磁盤上選擇一個(gè)文件夾目錄,作為掛載的磁盤路徑(例如C:\dos)
2. 在DOSBox啟動(dòng)的dos窗口中執(zhí)行命令:mount C C:\dos(代表著將本地的C:\dos路徑掛載到DOSBox的C盤路徑下),能把dos窗口的工作目錄切換到C盤,接下來就可以正常訪問被掛載的磁盤路徑下的內(nèi)容了。
3. 將前面提到過的debug.exe等文件都放在這個(gè)掛載的本地磁盤路徑下(例如C:\dos),通過DOSBox就可以兼容的運(yùn)行masm工具包中的程序和debug.exe了

添加自動(dòng)執(zhí)行腳本以避免重復(fù)操作:
由于上述DOSBox的磁盤掛載是臨時(shí)的,每次重新啟動(dòng)DOSBox后都需要重新輸入命令進(jìn)行掛載,太麻煩了。我們可以通過修改DOSBox配置的方式,免去這些重復(fù)的操作。
找到DOSBox安裝目錄下的DOSBox 0.74 Options.bat,使用系統(tǒng)自帶的記事本直接打開,暫不研究其它配置段的作用,找到最后的【autoexec】段,配置在【autoexec】的內(nèi)容會(huì)作為命令在DOSBox啟動(dòng)時(shí)按順序被自動(dòng)執(zhí)行。
將掛載磁盤操作命令配置在【autoexec】段中能避免重復(fù)操作。修改并保存配置文件后,重新啟動(dòng)DOSBox,發(fā)現(xiàn)配置中添加的命令會(huì)被自動(dòng)執(zhí)行。

2. 8086debug模式介紹
在搭建好了8086匯編的開發(fā)環(huán)境后,接下來介紹8086的debug模式。執(zhí)行debug.exe以進(jìn)入debug調(diào)試模式,在dos中通過輸入命令的方式進(jìn)行交互。

debug模式下有20多種不同命令,限于篇幅這里只會(huì)介紹幾個(gè)以后實(shí)驗(yàn)時(shí)常用到的命令。(通過回車執(zhí)行命令,DOS下的命令默認(rèn)是不區(qū)分大小寫的)
R命令查看/改變CPU寄存器內(nèi)容
R命令的作用是查看和修改debug模式下CPU中寄存器的值。
(-r)單獨(dú)的輸入r,可以查看當(dāng)前CPU的內(nèi)容
(-r 寄存器名) r加上寄存器名可以在接下來的":"提示后輸入新的值,以達(dá)到修改對(duì)應(yīng)寄存器內(nèi)容的目的(示例中第二行 AX 0000表示修改前寄存器AX的值為0000)

D命令 查看內(nèi)存中的內(nèi)容
D命令的作用是查看內(nèi)存中的內(nèi)容。
D命令有許多不同的傳參方式可供使用,先介紹最易理解的(段地址:偏移地址)查看方式。D命令默認(rèn)會(huì)顯示尋址地址開始的后128個(gè)內(nèi)存單元的內(nèi)容,以16進(jìn)制的方式顯示(每個(gè)內(nèi)存單元8位,一行最多16個(gè)內(nèi)存單元),而最右邊會(huì)將內(nèi)存單元中的二進(jìn)制數(shù)據(jù)以ascll碼的形式翻譯展示。

有時(shí),我們只想聚焦于某一部分內(nèi)存地址的內(nèi)容,而默認(rèn)展示的內(nèi)存視圖不是很方便。
D命令提供了另外一種訪問內(nèi)存的方式(段地址:偏移起始地址 偏移終止地址),其能夠展示(段地址:偏移起始地址 至 段地址:偏移終止地址)的內(nèi)存信息,范圍兩端均為閉區(qū)間。

E命令 改變內(nèi)存中的內(nèi)容
E命令的作用是改變內(nèi)存中的內(nèi)容。
和對(duì)CPU中寄存器的查看,修改不同,對(duì)內(nèi)存進(jìn)行查看和修改較為復(fù)雜,為此debug設(shè)計(jì)了兩個(gè)不同的命令分別進(jìn)行控制(E命令修改內(nèi)存、D命令查看內(nèi)存)。
通過(E 起始地址 數(shù)據(jù)1 數(shù)據(jù)2 數(shù)據(jù)3...)命令可以修改內(nèi)存中以起始地址開始,順序的N個(gè)內(nèi)存單元的值(N為實(shí)際參數(shù)傳遞的數(shù)量)。

也可以和R命令修改CPU中寄存器值類似的,通過提示來修改特定內(nèi)存單元的值。00.12 00代表內(nèi)存單元在修改前的值,12是我們手動(dòng)輸入的、需要修改的新值。

可以通過E命令向內(nèi)存輸入對(duì)應(yīng)的機(jī)器指令,因?yàn)闄C(jī)器指令也是數(shù)據(jù)的一種。
有以下指令(左側(cè)為機(jī)器碼,右側(cè)為對(duì)應(yīng)的匯編指令):
B80100 mov ax,0001
BB0200 mov bx,0002
01D8 add ax,bx
我們可以向內(nèi)存1000:0處寫入這些機(jī)器指令,以供接下來通過debug執(zhí)行這段機(jī)器指令 (執(zhí)行命令:E 1000:0 B8 01 00 BB 02 00 01 D8)。

U命令 將內(nèi)存數(shù)據(jù)轉(zhuǎn)換為匯編指令展示
U命令的作用是將內(nèi)存中的二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為匯編指令展示(反匯編)。
D命令能夠?qū)?nèi)存中的數(shù)據(jù)以16進(jìn)制或ascll碼的形式展現(xiàn)出來,但有時(shí)我們需要觀察的是內(nèi)存中的機(jī)器指令時(shí),D命令的視圖過于抽象,不利于理解。debug提供了U命令來解決這個(gè)問題。
對(duì)于前面我們?cè)?000:0處輸入的機(jī)器指令,使用 U 1000:0 命令(u 內(nèi)存地址)可以將內(nèi)存中的數(shù)據(jù)以匯編語言指令的方式進(jìn)行展示。

可以觀察到,左邊展示的是內(nèi)存地址,中間則是16進(jìn)制的內(nèi)存視圖,右邊展示的是內(nèi)存中數(shù)據(jù)所對(duì)應(yīng)的匯編指令(例如:1000:0000;B80100;MOV AX,0001)。
由于我們只輸入了三條匯編指令,而后面內(nèi)存中的數(shù)據(jù)并不是我們想要執(zhí)行的,但U命令卻依然將其以匯編指令的形式轉(zhuǎn)換并顯示出來了。
這也是前一篇博客所提到的,內(nèi)存中的數(shù)據(jù)完全是二進(jìn)制的,既可以將其看做普通的二進(jìn)制數(shù)據(jù)、十六進(jìn)制數(shù)據(jù)、ascll碼文本數(shù)據(jù),也可以視作程序指令,這些二進(jìn)制的"數(shù)據(jù)"的處理完全取決于如何對(duì)其進(jìn)行解釋。
T命令 單步執(zhí)行機(jī)器指令
T命令的作用是進(jìn)行單步機(jī)器指令的調(diào)試
以上文通過E命令寫入內(nèi)存1000:0的三條指令舉例,介紹如何使用T命令來讓CPU執(zhí)行1000:0處的機(jī)器指令。T命令用于單步調(diào)試,一次只會(huì)執(zhí)行一條機(jī)器指令。
8086CPU在運(yùn)行時(shí)會(huì)將CS:IP寄存器所指向的內(nèi)存單元中的內(nèi)容解釋為指令執(zhí)行,要將內(nèi)存1000:0處的內(nèi)容作為指令執(zhí)行必須先修改CS、IP兩個(gè)寄存器的值,使之指向1000:0。

先執(zhí)行一次T命令,1000:0處的指令(mov ax,0001)便會(huì)被執(zhí)行,可以觀察到寄存器ax的值已經(jīng)變成了0001;同時(shí)寄存器IP的值增加了3(mov ax,0001的指令長(zhǎng)度為3),此時(shí)CS:IP指向的便是位于1000:3處的下一條指令(mov bx,0002),在視圖的最后一行中也有所體現(xiàn)。

再執(zhí)行一次T命令,會(huì)執(zhí)行1000:3處的指令(mov bx,0002),可以觀察到寄存器bx的值變成了0002;寄存器IP的值又增加了3(mov bx,0002的指令長(zhǎng)度也是3),此時(shí)CS:IP指向的便是位于1000:6處的下一條指令(add ax,bx)。

最后執(zhí)行一次T命令,add ax,bx會(huì)被執(zhí)行(類似 ax=ax+bx)。寄存器ax的值已經(jīng)變成了之前寄存器ax和bx中的數(shù)據(jù)之和0003;寄存器IP的值增加了2(add ax,bx的指令長(zhǎng)度是2),CS:IP指向1000:8。

A命令 以匯編指令的形式向內(nèi)存中寫入內(nèi)容
A命令能夠以匯編指令的形式向內(nèi)存中寫入內(nèi)容
對(duì)于內(nèi)存操作,D命令可以查看內(nèi)存中的內(nèi)容,但如果想查看的是程序指令,顯然U命令更加方便;E命令可以向內(nèi)存中寫入數(shù)據(jù),但對(duì)于程序指令的寫入,直接操作二進(jìn)制機(jī)器碼的方式過于硬核。為此,debug提供了A命令,我們可以通過A命令以匯編指令的形式向內(nèi)存中寫入內(nèi)容。
通過A命令將(mov ax,0001,mov bx,0002,add ax,bx)三條指令寫入內(nèi)存1000:0處:

通過A命令進(jìn)行指令的寫入,和E命令達(dá)到的效果一樣,但使用起來卻更加便捷。A命令能夠自動(dòng)識(shí)別所輸入?yún)R編指令的長(zhǎng)度,正確的在內(nèi)存中寫入程序指令。
debug提供了D、E兩種命令用于對(duì)內(nèi)存進(jìn)行通用的操作(純二進(jìn)制、十六進(jìn)制數(shù)據(jù)的讀、寫)。
對(duì)于程序指令,debug提供了U、A兩種命令以更人性化的方式來讀寫內(nèi)存中的指令內(nèi)容。
三 總結(jié)
在debug模式下可以模擬8086匯編非常自由的控制CPU和內(nèi)存,這也是匯編語言的強(qiáng)大之處和魅力所在。
貼近硬件底層的編程能夠讓我們編寫出來的程序非常高效,但也存在一些問題:
1.內(nèi)存中的內(nèi)容被當(dāng)做指令還是數(shù)據(jù)來處理完全取決于如何解釋,編程時(shí)稍有不慎就會(huì)導(dǎo)致CPU執(zhí)行一些不應(yīng)該執(zhí)行的指令,甚至造成巨大的破壞。
2.在未來還會(huì)介紹如何使用匯編語言來實(shí)現(xiàn)高級(jí)語言中出現(xiàn)的結(jié)構(gòu)體、數(shù)組等概念。這些數(shù)據(jù)結(jié)構(gòu)完全是程序邏輯上的,內(nèi)存本身可沒有這些功能。因此在使用匯編訪問內(nèi)存中結(jié)構(gòu)化的數(shù)據(jù)時(shí),一不小心就會(huì)出現(xiàn)內(nèi)存訪問越界,錯(cuò)位等問題。
3.匯編語言的抽象程度過低,許多在高級(jí)語言中很簡(jiǎn)單的功能在匯編中也需要很多的代碼來實(shí)現(xiàn)(匯編實(shí)現(xiàn)的控制臺(tái)打印helloworld可能是常用語言中最繁瑣的了)。
編程語言的貼近底層與機(jī)器高效性如果站在更高的角度上看其實(shí)是一把雙刃劍:直接操控底層的機(jī)器方便,機(jī)器執(zhí)行效率高的同時(shí),也是危險(xiǎn)、開發(fā)效率底下的。匯編語言程序員不得不付出巨大的精力來仔細(xì)思考、斟酌這些底層機(jī)器層面的細(xì)節(jié),以避免出現(xiàn)相關(guān)bug,大大降低了開發(fā)效率。這也是高級(jí)語言誕生,并不斷發(fā)展的主要原因。
高級(jí)語言大家族中按抽象程度來看,從偏底層的C,C++到j(luò)ava、python等,再到目前抽象程度最高的lisp。隨著抽象程度的提高,離機(jī)器底層越遠(yuǎn),執(zhí)行效率通常也隨之降低。但程序員所需要考慮的機(jī)器細(xì)節(jié)也就越少,能更專注于業(yè)務(wù)邏輯,進(jìn)而提高了開發(fā)效率。比如在使用C編程時(shí)還需要仔細(xì)考慮指針錯(cuò)誤,堆上無用內(nèi)存回收等問題,到了更高級(jí)的java、python中,這些問題都交由編譯器、虛擬機(jī)解決了,對(duì)開發(fā)人員也幾乎透明了。
天下沒有免費(fèi)的午餐,在選擇適合的編程語言開發(fā)程序時(shí),需要在機(jī)器執(zhí)行效率和開發(fā)效率間做出取舍。但隨著科學(xué)技術(shù)的發(fā)展,計(jì)算機(jī)硬件會(huì)越來越強(qiáng)大,對(duì)機(jī)器效率的擔(dān)憂會(huì)越來越少,對(duì)程序開發(fā)效率的考慮將占據(jù)主導(dǎo)地位,越來越多的程序?qū)?huì)傾向于使用抽象程度更高的編程語言進(jìn)行開發(fā)。
雖然需要使用匯編語言的場(chǎng)合越來越少,但對(duì)匯編語言和底層機(jī)器硬件有一定的了解的話,依然能夠幫助程序員更深刻的理解上層的知識(shí)內(nèi)容、寫出更高效的程序。
畢竟,人類是無法抽象、封裝到完美無缺的,有時(shí)還是你需要跳進(jìn)下水道,深入底層一探究竟的。
總結(jié)
以上所述是小編給大家介紹的8086匯編開發(fā)環(huán)境搭建和Debug模式介紹,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
匯編語言 and和or邏輯運(yùn)算指令的實(shí)現(xiàn)
這篇文章主要介紹了匯編語言 and,or邏輯運(yùn)算指令的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01
計(jì)算機(jī)系統(tǒng)匯編語言和機(jī)器語言深入理解
這篇文章主要為大家介紹了計(jì)算機(jī)系統(tǒng)匯編語言和機(jī)器語言深入理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
淺析ELF轉(zhuǎn)二進(jìn)制允許把 Binary 文件加載到任意位置
本文通過 eip + 偏移地址 實(shí)現(xiàn)了運(yùn)行時(shí)計(jì)算數(shù)據(jù)地址,不再需要把 Binary 文件裝載到固定的位置。本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2020-02-02

