§4.5 8086匯編語言程序設(shè)計(jì)
本節(jié)概述
本節(jié)主要講述匯編程序的幾種結(jié)構(gòu)。
教學(xué)目標(biāo)
使讀者掌握幾種程序結(jié)構(gòu),編寫程序的步驟。
學(xué)習(xí)內(nèi)容
順序結(jié)構(gòu)
分支結(jié)構(gòu)
循環(huán)結(jié)構(gòu)
子程序結(jié)構(gòu)
重點(diǎn)難點(diǎn)
程序設(shè)計(jì)的幾種結(jié)構(gòu)。
學(xué)習(xí)方法
熟練掌握幾種程序設(shè)計(jì)的結(jié)構(gòu)。
關(guān)鍵字
順序 分支 循環(huán)
參考資料
1、《微型計(jì)算機(jī)技術(shù)及應(yīng)用》,戴梅萼等編著,第二版,清華大學(xué)出版社
2、《微型計(jì)算機(jī)原理》,季維法等編著,第一版,電子科技大學(xué)出版社
3、《微型計(jì)算機(jī)原理—常見題型解析及模擬題》,武自芳主編,西北工業(yè)大學(xué)出版社
4、《80X86/80X87匯編語言程序設(shè)計(jì)》,洪志全等編著,電子科技大學(xué)出版社
§4.5.1概述
通過前面幾節(jié)的介紹,我們對(duì)8086匯編語言源程序的基本概念有了比較清楚的認(rèn)識(shí),為了更高的質(zhì)量、高效率地進(jìn)行匯編語言程序設(shè)計(jì),還必須很好地程序設(shè)計(jì)的方法。
一般來說,匯編語言程序設(shè)計(jì)的技巧性是比較強(qiáng)的,即使對(duì)于同一個(gè)問題,不同的程序員編寫出來的程序可能相差很大,這對(duì)于計(jì)算機(jī)軟件的生產(chǎn)和推廣應(yīng)用都帶來了極大的困難。因此,在計(jì)算機(jī)科學(xué)中提出了編制程序工程化的設(shè)計(jì)方法。集體地說,就是在軟件中采用模塊結(jié)構(gòu)話的程序設(shè)計(jì)方法。所以,一個(gè)好的程序不僅能正常運(yùn)行,完成預(yù)定任務(wù),還應(yīng)滿足下列設(shè)計(jì)要求:
(1) 正常運(yùn)行,完成預(yù)定任務(wù)。
(2) 結(jié)構(gòu)清晰,程序簡(jiǎn)明、易讀、易調(diào)試、易維護(hù)(修改、擴(kuò)充)。
(3) 運(yùn)行速度快。
(4) 占用內(nèi)存少。
程序執(zhí)行速度快,又要占內(nèi)存空間少,兩者是有矛盾的,應(yīng)權(quán)衡利弊,側(cè)重某一個(gè)方面來設(shè)計(jì)。隨著計(jì)算機(jī)應(yīng)用的發(fā)展,程序的日漸龐大和復(fù)雜,使程序模塊化,寫好程序文件,以便于閱讀、調(diào)試和擴(kuò)展,以顯得越來越重要。從程序設(shè)計(jì)整體看,可分為如下幾個(gè)基本步驟:
(1) 全面分析問題,抽象出數(shù)學(xué)模型。(有些簡(jiǎn)單問題可以根據(jù)實(shí)際經(jīng)驗(yàn)編程)。
(2) 確定算法。
(3) 繪制流程圖。對(duì)于復(fù)雜程序,確定需要的模塊,畫出模塊間的結(jié)構(gòu)圖及各模塊的流程圖。
(4) 定義數(shù)據(jù)變量,分配存儲(chǔ)空間和工作單元。
(5) 編寫程序代碼。(按所使用的語言、軟件、硬件平臺(tái)編寫)。
(6) 靜態(tài)檢查、上機(jī)調(diào)試。
在程序設(shè)計(jì)中,為了使程序結(jié)構(gòu)清晰,應(yīng)采用結(jié)構(gòu)化程序設(shè)計(jì)方法,常用的程序基本結(jié)構(gòu)有:順序結(jié)構(gòu)、分支結(jié)構(gòu)、循環(huán)結(jié)構(gòu)、子程序結(jié)構(gòu)。
§4.5.2 順序結(jié)構(gòu)
順序結(jié)構(gòu)的程序一般是簡(jiǎn)單程序,它按順序執(zhí)行,無分支、循環(huán)、轉(zhuǎn)移,順序結(jié)構(gòu)的控制流程如圖所示。

§4.5.3 分支結(jié)構(gòu)
根據(jù)不同的條件,程序轉(zhuǎn)移到不同的分支,分支結(jié)構(gòu)的基本形式如圖4-6所示。
以條件"ZF=0"為例。
當(dāng)兩個(gè)分支合并時(shí),要特別注意第一個(gè)分支結(jié)束時(shí),跳轉(zhuǎn)到和并點(diǎn)如圖4-7所示。

為了避免分支及合并時(shí)出錯(cuò),一般在程序框圖中,標(biāo)識(shí)出主要點(diǎn)處的標(biāo)號(hào)。
程序的分支通過轉(zhuǎn)移指令來實(shí)現(xiàn),因此轉(zhuǎn)移指令的特點(diǎn)是改變程序執(zhí)行順序。轉(zhuǎn)移指令已經(jīng)在8086指令系統(tǒng)中講到。
§5.5.4 循環(huán)結(jié)構(gòu)
循環(huán)是在一定條件下重復(fù)執(zhí)行稱為"循環(huán)體"的程序段。循環(huán)前,應(yīng)當(dāng)給循環(huán)條件賦初值,在循環(huán)過程中,必須修改循環(huán)條件。
根據(jù)判別循環(huán)條件的時(shí)機(jī),有兩種基本循環(huán)結(jié)構(gòu),如圖4-8、圖4-9:

循環(huán)結(jié)構(gòu)可以用條件轉(zhuǎn)移指令(JZ、JNZ等)、循環(huán)指令(LOOP、LOOPZ等)實(shí)現(xiàn)。
指令系統(tǒng)提供了若干條設(shè)計(jì)循環(huán)結(jié)構(gòu)的循環(huán)控制指令,循環(huán)控制指令可以同時(shí)完成修改循環(huán)控制記數(shù)、檢測(cè)條件并控制轉(zhuǎn)移的工作。因此循環(huán)控制指令實(shí)現(xiàn)控制循環(huán)結(jié)構(gòu)更加簡(jiǎn)便。
循環(huán)程序設(shè)計(jì)中的重要問題是正確地控制循環(huán),保證循環(huán)的正常執(zhí)行和結(jié)束。如果循環(huán)控制哦于錯(cuò),就會(huì)導(dǎo)致循環(huán)不能完成預(yù)定的功能,或者循環(huán)不能結(jié)束,此時(shí)稱為死循環(huán),除非特殊需要,程序中不應(yīng)出下死循環(huán)??刂蒲h(huán)的方法通常分為兩大類:
(1)記數(shù)循環(huán)(用語循環(huán)次數(shù)已知的情況)。
(2)條件循環(huán)(用語循環(huán)次數(shù)不確定的情況)。
在條件循環(huán)方法中,可以根據(jù)需要設(shè)置各種豐富、靈活的條件來控制循環(huán)。
§5.5.5子程序結(jié)構(gòu)
在大型程序中,有時(shí),一段相同的程序多次被使用,可以把這段程序單獨(dú)提出來編寫,稱為"子程序",需要該段程序時(shí),用CALL指令調(diào)用子程序,這種編程處理方法,稱為"子程序結(jié)構(gòu)"。 相對(duì)于子程序,調(diào)用程序稱為主程序。
當(dāng)主程序與子程序不在同一個(gè)代碼段時(shí),稱為段間調(diào)用;當(dāng)主程序與子程序在同一個(gè)代碼段時(shí),稱為段內(nèi)調(diào)用。子程序可以調(diào)用子程序,稱為子程序"嵌套"。 子程序調(diào)用子程序的特例是子程序調(diào)用自身,稱為"遞歸",如圖4-10所示。

子程序可以有入口參數(shù)和/或出口參數(shù)。入口參數(shù)作為主程序傳遞給子程序處理的數(shù)據(jù),出口參數(shù)是子程序處理的結(jié)果。
編寫子程序的要求:
(1)保護(hù)寄存器與工作單元
如果子程序要用到某些寄存器或存儲(chǔ)單元,而它們的內(nèi)容在子程序返回后還需要使用。為了不破壞原有信息,應(yīng)將它們的內(nèi)容壓入堆棧保護(hù),或者存入一些空閑存儲(chǔ)器單元或寄存器,返回之前再恢復(fù)這些信息。注意:數(shù)據(jù)的出棧和圖棧冊(cè)順序是相反的。
(2)正確使用堆棧
調(diào)用程序轉(zhuǎn)入子程序前,在堆棧棧頂保存了斷點(diǎn)的地址,當(dāng)子程序執(zhí)行RET指令時(shí),則將從棧頂彈出斷點(diǎn)地址,以便返回到調(diào)用程序。如果子程序執(zhí)行期間需要使用堆棧暫存數(shù)據(jù),則必須成對(duì)地執(zhí)行PUSH和POP指令,以保證執(zhí)行RET指令前,堆棧棧頂恢復(fù)到剛進(jìn)入到子程序時(shí)的位置,使RET指令能正確地彈出斷點(diǎn)地址。
(3)子程序中應(yīng)有內(nèi)部文檔
為了使子程序可讀性好,可理解性好,便于使用,子程序中應(yīng)當(dāng)給出必要說明和適當(dāng)?shù)恼Z句注釋,這些說明和注釋稱為內(nèi)部文檔。
通常子程序頭部給出下列說明:
·子程序名
·功能描述:功能、性能指標(biāo)等
·子程序的入口參數(shù)、出口參數(shù)
·子程序使用的寄存器、存儲(chǔ)單元
·子程序所調(diào)用的其它子程序的名字
(4)參數(shù)傳遞
通過調(diào)用程序傳遞給子程序的參數(shù),可以使子程序的每次調(diào)用完成不同要求的具體操作,增加子程序的靈活性。例如,一個(gè)子程序的功能是從一個(gè)任意長(zhǎng)度的任意字符串中查找一個(gè)指定字符串出現(xiàn)的位置。由調(diào)用程序?qū)蓚€(gè)字符串的起始地址和字符串長(zhǎng)度傳遞給子程序,子程序便可完成一次具體的查找操作,然后將子字符串的位置指針再返回給調(diào)用程序。調(diào)用程序傳遞給子程序的參數(shù)稱為入口參數(shù),子程序返回給調(diào)用程序的數(shù)據(jù)或地址稱為出口參數(shù)。正因?yàn)樽映绦蚣纯梢越邮苷{(diào)用程序傳遞的參數(shù),也可以返回參數(shù)給調(diào)用程序,才使子程序更加靈活、方便而具有通用性。
§4.6 實(shí)數(shù)運(yùn)算
本節(jié)概述
本節(jié)主要講述實(shí)數(shù)的運(yùn)算和數(shù)學(xué)處理器的編程結(jié)構(gòu)和它的指令。
教學(xué)目標(biāo)
了解實(shí)數(shù)的運(yùn)算,實(shí)數(shù)的編碼,數(shù)學(xué)微處理器的編程結(jié)構(gòu)和它的指令。
本節(jié)內(nèi)容
實(shí)數(shù)的運(yùn)算
實(shí)數(shù)的編碼
數(shù)學(xué)協(xié)處理器的編程結(jié)構(gòu)
CPU與數(shù)學(xué)協(xié)處理器的軟件協(xié)調(diào)
數(shù)學(xué)協(xié)處理器的指令
實(shí)數(shù)運(yùn)算程序例題
重點(diǎn)難點(diǎn)
實(shí)數(shù)的編碼,數(shù)學(xué)微處理器的編程結(jié)構(gòu)和它的指令。
學(xué)習(xí)方法
熟練掌握實(shí)數(shù)的編碼,數(shù)學(xué)微處理器的編程結(jié)構(gòu)和它的指令。
關(guān)鍵字
運(yùn)算 編碼 編程結(jié)構(gòu) 指令
參考資料
1、《微型計(jì)算機(jī)技術(shù)及應(yīng)用》,戴梅萼等編著,第二版,清華大學(xué)出版社
2、《微型計(jì)算機(jī)原理》,季維法等編著,第一版,電子科技大學(xué)出版社
3、《微型計(jì)算機(jī)原理—常見題型解析及模擬題》,武自芳主編,西北工業(yè)大學(xué)出版社
4、《80X86/80X87匯編語言程序設(shè)計(jì)》,洪志全等編著,電子科技大學(xué)出版社
§4.6.1實(shí)數(shù)的運(yùn)算
8086/80286/80386等X86 CPU 無實(shí)數(shù)運(yùn)算指令,若要進(jìn)行實(shí)數(shù)運(yùn)算,可有以下兩種途徑:
?、?使用8087/80287/80387數(shù)學(xué)協(xié)處理器(numeric coprocessor )。
?、?用X86 CPU 的整數(shù)指令仿真實(shí)數(shù)運(yùn)算。
在80386及以前的系統(tǒng)中,數(shù)學(xué)協(xié)處理器與主處理器(CPU)分別制造為單獨(dú)的芯片,兩者通過外部聯(lián)線相互操作,數(shù)學(xué)協(xié)處理器也稱為NPX(numeric processor extension)。
在80486及以后的系統(tǒng)中,一般把數(shù)學(xué)協(xié)處理器與主處理器集成到一塊芯片上,整體稱為CPU,集成后的數(shù)學(xué)協(xié)處理器稱為該CPU的浮點(diǎn)運(yùn)算單元FPU(float process unit)。
§4.6.2 實(shí)數(shù)的編碼
在計(jì)算機(jī)中,任何信息均是通過編碼表示的,實(shí)數(shù)也不例外。任何實(shí)數(shù),均可規(guī)格化 (Normalized) 為:R=±1.MX2N,1為整數(shù),M為尾數(shù),N為指數(shù)。
在這種表示方法中,二進(jìn)制小數(shù)點(diǎn)的位置隨指數(shù)部分移動(dòng),稱為"浮點(diǎn)表示",因此,常將實(shí)數(shù)運(yùn)算稱為"浮點(diǎn)運(yùn)算"。
用編碼表示正/負(fù)、整數(shù)、尾數(shù)、指數(shù),則可表示一個(gè)實(shí)數(shù)。按編碼使用的二進(jìn)制位數(shù)不同,程序中可使用短實(shí)數(shù)、長(zhǎng)實(shí)數(shù)和臨時(shí)實(shí)數(shù),分別用偽指令DD、DQ、DT定義。
DD:定義一個(gè)短實(shí)數(shù),或稱單精度實(shí)數(shù), 在內(nèi)存中占32位(4字節(jié))
DQ:定義一個(gè)長(zhǎng)實(shí)數(shù),或稱雙精度實(shí)數(shù), 在內(nèi)存中占64位(8字節(jié))
DT:定義一個(gè)臨時(shí)實(shí)數(shù),或稱擴(kuò)展精度實(shí)數(shù),占80位(10字節(jié)),一般用于數(shù)學(xué)協(xié)處理器內(nèi)部運(yùn)算。
匯編程序MASM將以上十進(jìn)制實(shí)數(shù)編碼為二進(jìn)制。編碼的格式有兩種:IEEE格式和Microsoft格式。
以下介紹IEEE格式。
1、 短實(shí)數(shù)的編碼
S(31)指數(shù)N(30~23),8位尾數(shù)M(BIT22~BIT0),23位
表示的實(shí)數(shù)值R=±1.M×2(N-127)
整數(shù)部分1是固定的,未在編碼中表示出來。
指數(shù)部分減去一個(gè)值,是為了避免出現(xiàn)負(fù)值。
2、長(zhǎng)實(shí)數(shù)的編碼
S(63)指數(shù)N(62~52),11位尾數(shù)M(BIT51~BIT0),52位
表示的實(shí)數(shù)值R=±1.M×2(N-1023)
整數(shù)部分1是固定的,未在編碼中表示出來。
3、臨時(shí)實(shí)數(shù)的編碼:
S(79)指數(shù)N(78~64),15位1(63)尾數(shù)M(62~0),63位
表示的實(shí)數(shù)值R=±1.M×2(N-16383)
整數(shù)部分1用BIT63表示,便于數(shù)學(xué)協(xié)處理器運(yùn)算。
