8086彙編語言學習(二) 8086彙編開發環境搭建和Debug模式介紹

1. 8086彙編開發環境搭建

  在上篇博客中簡單的介紹了8086彙編語言。工欲善其事,必先利其器,在8086彙編語言正式開始學習以前,先介紹一下如何搭建8086彙編的開發環境。php

  彙編語言設計之初是用於在沒有操做系統的裸機上直接操做硬件的,但對於大部分人來講,在8086裸機上直接進行編程將會面臨各類困難。好在咱們可使用軟件模擬器來模擬硬件進行8086的學習實踐。在《彙編語言》中做者推薦經過windows環境下的masmdebug進行學習。java

masm介紹:python

  masm是一款DOS下的彙編工具包,在8086彙編的學習中咱們須要其中的幾個文件,分別是masm.exelink.exe程序員

  masm.exe 彙編器,用於將文本格式的彙編語言源文件編譯爲.obj結尾的二進制文件,其生成的.obj結尾的二進制目標文件是被編譯的源文件的對應的機器碼。單獨的源程序目標文件一般是沒法直接運行的,還須要和互相依賴的其它一樣編譯完成的二進制文件連接在一塊兒才能生成最終的可執行文件(好比所須要的靜態庫函數) 。所以,obj文件一般也被叫作中間文件。編程

  link.exe 連接器,obj文件須要經過連接才能轉換成可執行程序,而連接器就是負責完成這一任務的。連接器能將多個obj目標文件以及其所依賴的庫程序進行統一處理(例如多個目標文件中指令、數據內存地址的偏移處理),並生成可執行文件。windows

debug介紹:數組

  debug.exe 調試器,windows提供了一個在dos中調試8086彙編程序的工具debug.exe,提供了展現程序運行時CPU中各寄存器、內存中數據指令級的單步調試等功能。debug程序的使用會在本篇博客的後半段進行詳細介紹。數據結構

64位操做系統兼容性問題:

  因爲《彙編語言》一書出版較早,當時的windows系統仍是32位的,32位windows系統都默認安裝了masm與debug,能打開dos窗口直接使用。但目前廣泛使用的、新的windows 64位操做系統中卻並無默認提供masm工具包和debug.exe,同時masm、debug也與64位的windows系統版本不兼容。編程語言

想在64位的windows系統下使用masm、debug有兩個經常使用方法:函數

  1. 經過虛擬機安裝一個老版本的windows操做系統(推薦windows xp)

  2. 經過DOSBox這一輕量級的ms-dos模擬器來運行,但上文所述的依賴程序需單獨下載(百度網盤下載連接:https://pan.baidu.com/s/158NKJoea6_Y4UmCFsDP0oQ#list/path=%2F)

  我的推薦第二種方法,下面介紹如何在windows64位操做系統下使用DOSBox來搭建8086彙編語言的開發環境。

DOSBox安裝與使用

DOSBox下載安裝:

  DOSBox能夠在官網下載,這裏也提供了百度網盤的下載連接(0.74版本):https://pan.baidu.com/s/11_GcPpTqJm78N8xEXZpPMw

  安裝完畢後,找到安裝目錄下的DOSBox.exe並啓動,能看到以下圖界面。

  

  做爲dos的模擬器和普通的dos窗口沒有明顯區別,可是初始時並不能直接訪問到本地磁盤,須要先將本地磁盤掛載到DOSBox中

DOSBox掛載本地磁盤:

  1. 在本地操做系統磁盤上選擇一個文件夾目錄,做爲掛載的磁盤路徑(例如C:\dos)

  2. 在DOSBox啓動的dos窗口中執行命令:mount C C:\dos(表明着將本地的C:\dos路徑掛載到DOSBox的C盤路徑下),能把dos窗口的工做目錄切換到C盤,接下來就能夠正常訪問被掛載的磁盤路徑下的內容了。

  3. 將前面提到過的debug.exe等文件都放在這個掛載的本地磁盤路徑下(例如C:\dos),經過DOSBox就能夠兼容的運行masm工具包中的程序和debug.exe了

  

添加自動執行腳本以免重複操做:

  因爲上述DOSBox的磁盤掛載是臨時的,每次從新啓動DOSBox後都須要從新輸入命令進行掛載,太麻煩了。咱們能夠經過修改DOSBox配置的方式,免去這些重複的操做。

  找到DOSBox安裝目錄下的DOSBox 0.74 Options.bat,使用系統自帶的記事本直接打開,暫不研究其它配置段的做用,找到最後的【autoexec】段,配置在【autoexec】的內容會做爲命令在DOSBox啓動時按順序被自動執行。  

  將掛載磁盤操做命令配置在【autoexec】段中能避免重複操做。修改並保存配置文件後,從新啓動DOSBox,發現配置中添加的命令會被自動執行。

  

2. 8086debug模式介紹

  在搭建好了8086彙編的開發環境後,接下來介紹8086的debug模式。執行debug.exe以進入debug調試模式,在dos中經過輸入命令的方式進行交互。

  

  debug模式下有20多種不一樣命令,限於篇幅這裏只會介紹幾個之後實驗時經常使用到的命令。(經過回車執行命令,DOS下的命令默認是不區分大小寫的)

R命令 查看/改變CPU寄存器內容

  R命令的做用是查看和修改debug模式下CPU中寄存器的值。

  (-r) 單獨的輸入r,能夠查看當前CPU的內容

  (-r 寄存器名) r加上寄存器名能夠在接下來的":"提示後輸入新的值,以達到修改對應寄存器內容的目的(示例中第二行 AX 0000表示修改前寄存器AX的值爲0000)  

D命令 查看內存中的內容

  D命令的做用是查看內存中的內容。

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

  

  有時,咱們只想聚焦於某一部份內存地址的內容,而默認展現的內存視圖不是很方便。

  D命令提供了另一種訪問內存的方式(段地址:偏移起始地址 偏移終止地址),其可以展現(段地址:偏移起始地址 至 段地址:偏移終止地址)的內存信息,範圍兩端均爲閉區間。

  

E命令 改變內存中的內容

  E命令的做用是改變內存中的內容

  和對CPU中寄存器的查看,修改不一樣,對內存進行查看和修改較爲複雜,爲此debug設計了兩個不一樣的命令分別進行控制(E命令修改內存、D命令查看內存)。

  經過(E 起始地址 數據1 數據2 數據3...)命令能夠修改內存中以起始地址開始,順序的N個內存單元的值(N爲實際參數傳遞的數量)。

  

   也能夠和R命令修改CPU中寄存器值相似的,經過提示來修改特定內存單元的值。00.12  00表明內存單元在修改前的值,12是咱們手動輸入的、須要修改的新值。

  

  能夠經過E命令向內存輸入對應的機器指令,由於機器指令也是數據的一種

有如下指令(左側爲機器碼,右側爲對應的彙編指令):

  B80100  mov ax,0001

  BB0200  mov bx,0002

  01D8      add ax,bx

  咱們能夠向內存1000:0處寫入這些機器指令,以供接下來經過debug執行這段機器指令 (執行命令:E 1000:0 B8 01 00 BB 02 00 01 D8)。

  

U命令 將內存數據轉換爲彙編指令展現

  U命令的做用是將內存中的二進制數據轉換爲彙編指令展現(反彙編)。

  D命令可以將內存中的數據以16進制或ascll碼的形式展示出來,但有時咱們須要觀察的是內存中的機器指令時,D命令的視圖過於抽象,不利於理解。debug提供了U命令來解決這個問題。

  對於前面咱們在1000:0處輸入的機器指令,使用 U 1000:0 命令(u 內存地址)能夠將內存中的數據以彙編語言指令的方式進行展現。

  

  能夠觀察到,左邊展現的是內存地址,中間則是16進制的內存視圖,右邊展現的是內存中數據所對應的彙編指令(例如: 1000:0000B80100MOV AX,0001)。

  因爲咱們只輸入了三條彙編指令,然後面內存中的數據並非咱們想要執行的,但U命令卻依然將其以彙編指令的形式轉換並顯示出來了。

  這也是前一篇博客所提到的,內存中的數據徹底是二進制的,既能夠將其看作普通的二進制數據、十六進制數據、ascll碼文本數據,也能夠視做程序指令,這些二進制的"數據"的處理徹底取決於如何對其進行解釋

T命令 單步執行機器指令

  T命令的做用是進行單步機器指令的調試

  以上文經過E命令寫入內存1000:0的三條指令舉例,介紹如何使用T命令來讓CPU執行1000:0處的機器指令。T命令用於單步調試,一次只會執行一條機器指令。

  8086CPU在運行時會將CS:IP寄存器所指向的內存單元中的內容解釋爲指令執行,要將內存1000:0處的內容做爲指令執行必須先修改CS、IP兩個寄存器的值,使之指向1000:0。

  

   先執行一次T命令,1000:0處的指令(mov ax,0001)便會被執行,能夠觀察到寄存器ax的值已經變成了0001;同時寄存器IP的值增長了3(mov ax,0001的指令長度爲3),此時CS:IP指向的即是位於1000:3處的下一條指令(mov bx,0002),在視圖的最後一行中也有所體現

   

   再執行一次T命令,會執行1000:3處的指令(mov bx,0002),能夠觀察到寄存器bx的值變成了0002;寄存器IP的值又增長了3(mov bx,0002的指令長度也是3),此時CS:IP指向的即是位於1000:6處的下一條指令(add ax,bx)

  

  最後執行一次T命令,add ax,bx會被執行(相似 ax=ax+bx)。寄存器ax的值已經變成了以前寄存器ax和bx中的數據之和0003;寄存器IP的值增長了2(add ax,bx的指令長度是2),CS:IP指向1000:8。

  

A命令 以彙編指令的形式向內存中寫入內容

  A命令可以以彙編指令的形式向內存中寫入內容

  對於內存操做,D命令能夠查看內存中的內容,但若是想查看的是程序指令,顯然U命令更加方便;E命令能夠向內存中寫入數據,但對於程序指令的寫入,直接操做二進制機器碼的方式過於硬核。爲此,debug提供了A命令,咱們能夠經過A命令以彙編指令的形式向內存中寫入內容。

  經過A命令將(mov ax,0001,mov bx,0002,add ax,bx)三條指令寫入內存1000:0處:

  

  經過A命令進行指令的寫入,和E命令達到的效果同樣,但使用起來卻更加便捷。A命令可以自動識別所輸入彙編指令的長度,正確的在內存中寫入程序指令。

  debug提供了D、E兩種命令用於對內存進行通用的操做(純二進制、十六進制數據的讀、寫)。

  對於程序指令,debug提供了U、A兩種命令以更人性化的方式來讀寫內存中的指令內容。

三 總結

  在debug模式下能夠模擬8086彙編很是自由的控制CPU和內存,這也是彙編語言的強大之處和魅力所在。

貼近硬件底層的編程可以讓咱們編寫出來的程序很是高效,但也存在一些問題:

  1.內存中的內容被當作指令仍是數據來處理徹底取決於如何解釋,編程時稍有不慎就會致使CPU執行一些不該該執行的指令,甚至形成巨大的破壞。

  2.在將來還會介紹如何使用匯編語言來實現高級語言中出現的結構體、數組等概念。這些數據結構徹底是程序邏輯上的,內存自己可沒有這些功能。所以在使用匯編訪問內存中結構化的數據時,一不當心就會出現內存訪問越界,錯位等問題。

  3.彙編語言的抽象程度太低,許多在高級語言中很簡單的功能在彙編中也須要不少的代碼來實現(彙編實現的控制檯打印hello world多是經常使用語言中最繁瑣的了)。

  編程語言的貼近底層與機器高效性若是站在更高的角度上看實際上是一把雙刃劍:直接操控底層的機器方便,機器執行效率高的同時,也是危險、開發效率底下的。彙編語言程序員不得不付出巨大的精力來仔細思考、斟酌這些底層機器層面的細節,以免出現相關bug,大大下降了開發效率。這也是高級語言誕生,並不斷髮展的主要緣由。

  高級語言你們族中按抽象程度來看,從偏底層的C,C++到java、python等,再到目前抽象程度最高的lisp。隨着抽象程度的提升,離機器底層越遠,執行效率一般也隨之下降。但程序員所須要考慮的機器細節也就越少,能更專一於業務邏輯,進而提升了開發效率。好比在使用C編程時還須要仔細考慮指針錯誤,堆上無用內存回收等問題,到了更高級的java、python中,這些問題都交由編譯器、虛擬機解決了,對開發人員也幾乎透明瞭。

  天下沒有免費的午飯,在選擇適合的編程語言開發程序時,須要在機器執行效率和開發效率間作出取捨。但隨着科學技術的發展,計算機硬件會愈來愈強大,對機器效率的擔心會愈來愈少,對程序開發效率的考慮將佔據主導地位,愈來愈多的程序將會傾向於使用抽象程度更高的編程語言進行開發。

  雖然須要使用匯編語言的場合愈來愈少,但對彙編語言和底層機器硬件有必定的瞭解的話,依然可以幫助程序員更深入的理解上層的知識內容、寫出更高效的程序。

  畢竟,人類是沒法抽象、封裝到天衣無縫的,有時仍是你須要跳進下水道,深刻底層一探究竟的。

相關文章
相關標籤/搜索