微機(jī)原理及其應(yīng)用第五章_第1頁
微機(jī)原理及其應(yīng)用第五章_第2頁
微機(jī)原理及其應(yīng)用第五章_第3頁
微機(jī)原理及其應(yīng)用第五章_第4頁
微機(jī)原理及其應(yīng)用第五章_第5頁
已閱讀5頁,還剩82頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

第5章匯編語言程序設(shè)計(jì)內(nèi)容提要:本章介紹了匯編語言基本語法,匯編語言程序的實(shí)現(xiàn),匯編語言程序設(shè)計(jì)方法及應(yīng)用,并通過程序設(shè)計(jì)舉例說明了順序結(jié)構(gòu)程序設(shè)計(jì);分支結(jié)構(gòu)程序設(shè)計(jì);循環(huán)結(jié)構(gòu)程序設(shè)計(jì);子程序設(shè)計(jì)以及宏的定義和調(diào)用。學(xué)習(xí)要求:熟練掌握8086/8088微處理器匯編語言程序設(shè)計(jì)的方法及應(yīng)返回主目錄

通過前面的學(xué)習(xí)我們知道,計(jì)算機(jī)之所以能夠自動地工作,是因?yàn)橛?jì)算機(jī)能按照程序的安排執(zhí)行相應(yīng)的指令,編寫這些程序的語言就稱為計(jì)算機(jī)語言。計(jì)算機(jī)語言按照人類的語言習(xí)慣通常分為高級語言、中級語言和低級語言,與人類自然語言相差較大、接近于機(jī)器描述的計(jì)算機(jī)語言稱為低級語言,低級語言包括機(jī)器語言和匯編語言。本章主要介紹和計(jì)算機(jī)硬件系統(tǒng)緊密相關(guān)的匯編語言程序設(shè)計(jì)。

本章目錄5.1匯編語言基礎(chǔ)5.2匯編語言程序結(jié)構(gòu)5.3匯編語言程序設(shè)計(jì)小結(jié)第5章匯編語言程序設(shè)計(jì)基礎(chǔ)

在計(jì)算機(jī)內(nèi)部,控制計(jì)算機(jī)工作的指令都以二進(jìn)制代碼的形式出現(xiàn),這樣的指令稱為機(jī)器指令,用機(jī)器指令編寫的程序稱為機(jī)器語言程序??梢?,機(jī)器語言是二進(jìn)制編碼表示的命令和數(shù)據(jù)的總稱,是面向機(jī)器的,能夠被計(jì)算機(jī)直接識別和執(zhí)行的。然而,二進(jìn)制表述的機(jī)器語言既不直觀,又不便于記憶、閱讀和書寫,為了程序設(shè)計(jì)的方便,產(chǎn)生了匯編語言。匯編語言是一種符號語言,用與操作功能含義相應(yīng)的縮寫英文字符組成的助記符號作為編程使用的語言,來表示二進(jìn)制格式的指令代碼和變量地址。計(jì)算機(jī)在運(yùn)行匯編語言程序之前要先將其轉(zhuǎn)換成機(jī)器代碼,才能由計(jì)算機(jī)識別執(zhí)行,轉(zhuǎn)換的過程是由編譯程序來完成。5.1匯編語言基礎(chǔ)5.1.1

匯編語言概述

在匯編語言中,符號指令和機(jī)器指令通常是一一對應(yīng)的,匯編語言與機(jī)器語言相比編程簡單、便于交流,并且保留了機(jī)器語言與硬件系統(tǒng)聯(lián)系密切的特點(diǎn),所以,匯編語言仍然是面向機(jī)器的語言,在使用匯編語言時必須對相應(yīng)的計(jì)算機(jī)硬件有一定了解,CPU不同的計(jì)算機(jī),匯編語言也不同。由于機(jī)器不能直接執(zhí)行匯編語言源程序,所以必須先將源程序轉(zhuǎn)換成二進(jìn)制代碼表示的機(jī)器指令,完成這一功能的軟件就是匯編程序,在IBM-PC微型計(jì)算機(jī)系統(tǒng)中,目前廣泛使用的匯編程序是由Microsoft公司開發(fā)的宏匯編程序

—MASM。

同其它語言一樣,匯編語言的基本組成單位是語句,在匯編語言源程序中每個語句由四項(xiàng)組成,其格式如下:

[標(biāo)號:]操作項(xiàng)[操作數(shù)][;注釋]其中,操作項(xiàng)是必不可少的。5.1.2匯編語言語句格式

標(biāo)號是一個可選字段,由字母(A~Z、a~z)數(shù)字(0~9)及專用字符(?、.、@、-、$)組成的字符串,最長不超過31個字符,要求必須以字母開頭,用冒號與操作項(xiàng)分開。標(biāo)號實(shí)質(zhì)上是指令的符號地址,但并不是所有指令語句都有標(biāo)號。如果指令語句前有標(biāo)號,則程序的其他部分可以引用這個標(biāo)號,如程序中的JMP指令和CALL指令的轉(zhuǎn)移目標(biāo)由標(biāo)號指定,即JMP指令和CALL指令是根據(jù)標(biāo)號來確定它們之后要執(zhí)行的語句,可見標(biāo)號其實(shí)是指定了具體的指令地址,所以相同的標(biāo)號定義在同一程序中只允許出現(xiàn)一次。1、標(biāo)號字段

標(biāo)號有三種屬性:段、偏移量和類型。標(biāo)號的段屬性是定義標(biāo)號的程序段的段基值;標(biāo)號的偏移量屬性是表示該標(biāo)號在段內(nèi)的偏移地址,偏移量是一個16位的無符號數(shù);標(biāo)號的類型屬性有NEAR和FAR兩種,NEAR只能提供同一段內(nèi)的指令調(diào)用,F(xiàn)AR可以被其他段指令調(diào)用。

操作項(xiàng)是匯編語言程序中不可省略的主要部分,用指令助記符或定義符表示的機(jī)器指令操作碼,如:MOV、ADD等,它告訴CPU要完成什么具體操作。有的操作項(xiàng)帶有前綴,指令系統(tǒng)中允許與指令助記符一起出現(xiàn)的前綴是前綴指令和段超越前綴。2、操作項(xiàng)字段

操作數(shù)緊跟在操作項(xiàng)之后,具體指明操作項(xiàng)的指令對哪些變量或常數(shù)進(jìn)行操作,它可以包含兩個操作數(shù)、一個操作數(shù)或無操作數(shù)。如:MOV、ADD等指令要求有兩個操作數(shù),它們之間用逗號隔開;NEG、INC等指令只需要一個操作數(shù);而CLC等指令就不需要操作數(shù),因?yàn)椴僮鲾?shù)已隱含在指令助記符中了。操作數(shù)可以是數(shù)據(jù),也可以是存放數(shù)據(jù)的地址,所以可以作為操作數(shù)的有:常量、變量、表達(dá)式、寄存器和標(biāo)號。3、操作數(shù)字段

⑴常量常量是指令中的固定值,它們在程序運(yùn)行期間不發(fā)生變化,它可以分為數(shù)值常量和字符串常量。例如:立即數(shù)尋址時的立即數(shù);直接尋址時的地址;ASCII碼字符串等都屬于常量。在匯編語言源程序中,數(shù)值常量可以用二進(jìn)制數(shù)、八進(jìn)制數(shù)(O或Q)、十進(jìn)制數(shù)和十六進(jìn)制數(shù)來表示,但要用不同的后綴加以區(qū)別。要注意的是,匯編語言要求數(shù)值常量的第一位必須是數(shù)字,如:FFFFH應(yīng)寫成0FFFFH,否則匯編時會被誤作為標(biāo)號處理。

⑵變量變量是指存放在存儲器或寄存器中的數(shù)據(jù),這些數(shù)據(jù)隨著程序運(yùn)行可能隨時會發(fā)生變化。寄存器有固定的名字,如:AL、AX等;存儲器常以其地址或地址表達(dá)式的形式出現(xiàn)。應(yīng)該指出,變量也有段、偏移量和類型三個屬性。

⑶表達(dá)式表達(dá)式是操作數(shù)最常見的形式,其值由常數(shù)、變量、標(biāo)號通過運(yùn)算符連接,在匯編時計(jì)算確定。匯編語言中運(yùn)算符分為:算術(shù)運(yùn)算符、邏輯運(yùn)算符、關(guān)系運(yùn)算符、分析運(yùn)算符和屬性修改運(yùn)算符等。

①算術(shù)運(yùn)算符:常用的算術(shù)運(yùn)算符有:加(+)、減(-)、乘(×)、除(/)和模(MOD)等,算術(shù)運(yùn)算的結(jié)果是一個數(shù)值,對于表示存儲器地址的地址表達(dá)式加和減運(yùn)算才有意義。例如:

MOVAX,VARX+2

表示將VARX表示的地址加2后對應(yīng)的存儲單元內(nèi)的數(shù)據(jù)送AX。

②邏輯運(yùn)算符:邏輯運(yùn)算符包括:AND(邏輯“與”)、OR(邏輯“或”)、XOR(邏輯“異或”)、NOT(邏輯“非”),用于數(shù)值表達(dá)式中對數(shù)值進(jìn)行按位邏輯運(yùn)算,結(jié)果也是一個數(shù)值。例如:MOVAL,0FHAND35H

表示將0FH與35H按位邏輯“與”后得到的數(shù)值(05H)送AL。注意:邏輯運(yùn)算符AND、OR、XOR、NOT同時也是指令助記符,作為運(yùn)算符時在程序匯編時用作計(jì)算;作為指令助記符時是在程序執(zhí)行時用作計(jì)算的。例如:

ANDAX,VARTBAND8000H

表示將VARTB表示的地址與8000H按位邏輯“與”后,對應(yīng)的存儲單元內(nèi)的數(shù)據(jù)再與AX內(nèi)的數(shù)據(jù)進(jìn)行邏輯“與”??梢?,在匯編時計(jì)算VARTBAND8000H,得到的數(shù)值作為程序的一個操作數(shù);執(zhí)行程序時計(jì)算第一個AND,將前面得到的操作數(shù)與AX內(nèi)的數(shù)據(jù)進(jìn)行“與”運(yùn)算,結(jié)果送AX。

③關(guān)系運(yùn)算符:關(guān)系運(yùn)算符有EQ(等于)、NE(不等于)、LT(小于)、GT(大于)、LE(小于等于)、GE(大于等于)。關(guān)系運(yùn)算符必須有兩個操作數(shù),而且必須是兩個數(shù)值或是同一段內(nèi)的存儲單元地址。關(guān)系運(yùn)算符只能有兩個結(jié)果“0”或“1”,關(guān)系成立時運(yùn)算結(jié)果為0FFFFH,關(guān)系不成立時運(yùn)算結(jié)果為0。要注意的是,關(guān)系運(yùn)算符一般不單獨(dú)使用,常與其他運(yùn)算符結(jié)合起來使用。例如:MOVAX,4NE3

表示將4和3進(jìn)行是否不相等的判斷,結(jié)果送AX。這里由于4不等于3,所以該關(guān)系運(yùn)算結(jié)果應(yīng)為0FFFFH,并送寄存器AX。

④分析操作符:分析操作符包括OFFSET、SEG、TYPE、SIZE和LENGTH,它們的作用是把一個存儲單元地址分解為段地址和偏移地址。

1)OFFSET表示取標(biāo)號或變量地址的偏移量,例如:MOVDX,OFFSETSTRING

表示將STRING的偏移地址送DX寄存器,屬于立即數(shù)尋址方式。

2)SEG表示取標(biāo)號或變量的段地址。例如:

MOVBX,SEGTABLE1

表示將TABLE1的段地址送BX寄存器。

3)TYPE運(yùn)算結(jié)果是一個數(shù)值,表示存儲單元操作數(shù)的類型。運(yùn)算結(jié)果與操作數(shù)類型的對應(yīng)關(guān)系見表5-1。

例如:VARDW1234HARRAYDB56H?MOVAX,TYPEVARMOVBX,TYPEARRAY

上例中前兩句偽指令定義了變量VAR的類型為字,變量ARRAY的類型為字節(jié),后兩句將VAR、ARRAY的類型對應(yīng)數(shù)值送寄存器AX、BX,即執(zhí)行TYPE后AX的值應(yīng)為2,BX的值應(yīng)為1。表5-1TYPE運(yùn)算結(jié)果與操作數(shù)類型的對應(yīng)關(guān)系TYPE運(yùn)算結(jié)果操作數(shù)類型TYPE運(yùn)算結(jié)果操作數(shù)類型1BYTE(DB)-1NEAR2WORD(DW)-2FAR4DWORD(DD)4)LENGTH一般加在數(shù)組變量的前面,作用是計(jì)算數(shù)組變量占存儲單元的個數(shù)。若使用DUP,則執(zhí)行結(jié)果是外層DUP的給定值;若沒有使用DUP,則執(zhí)行結(jié)果為1。例如:

D1DB10DUP(0FH)D2DB‘ABCDEFGHIJK’?MOVBH,LENGTHD1MOVBL,LENGTHD2

前兩句偽指令定義變量D1、D2的類型為字節(jié),重復(fù)操作符DUP表示從D1開始連續(xù)設(shè)定10個字節(jié)的空間,且將內(nèi)容設(shè)定為0FH。后兩句執(zhí)行了LENGTH運(yùn)算后,結(jié)果分別為10和1,即執(zhí)行LENGTH后將10送BH,將1送BL。(5)SIZE

格式:SIZEvariable

匯編程序回送分配給該變量的字節(jié)數(shù)。值是LENGTH值和TYPE值的乘積。例①:

FEESDW100DUP(0) ;分配給FEES100個單元

MOVCX,SIZEFEES

匯編程序?qū)⑹蛊湫纬蔀椋篗OVCX,200

⑤屬性修改運(yùn)算符(類型轉(zhuǎn)換):屬性修改運(yùn)算符有PTR、THIS和SHORT,用于指定或修改變量、標(biāo)號和存儲器操作數(shù)的類型屬性,也稱綜合運(yùn)算符。

1)PTR用于指定或修改存儲單元操作數(shù)的類型。例如:

MOVWORDPTR[5000H],8

執(zhí)行PTR后指定存儲單元5000H為一個字單元,上面的語句是將數(shù)值8送地址為5000H的存儲單元,存儲單元類型為字,因此執(zhí)行語句后,[5000H]存儲單元的內(nèi)容為08H,[5001H]存儲單元的內(nèi)容為00H。注意,PTR的修改是臨時性的,僅在本語句中有效。2)THIS也是用來指定或修改存儲單元的類型。與PTR不同的是,該運(yùn)算建立指定類型的地址操作數(shù),其段地址和偏移量與下一個存儲單元地址相同,因此THIS運(yùn)算符更具有靈活性。例如:

BEGIN EQUTHISFAR PUSHAX

上述語句是使PUSHAX指令有一個具備FAR屬性的地址BEGIN,使得標(biāo)號BEGIN可以被其他段的JMP指令直接調(diào)用。3)SHORT用于指定某個標(biāo)號的類型為“短標(biāo)號”,即使當(dāng)前指令位置到指定標(biāo)號的距離在-128+127個字節(jié)的范圍內(nèi)

⑥其他運(yùn)算符:

1)冒號一般跟在段寄存器名之后,用于給存儲單元操作數(shù)指定段屬性,不必考慮存儲單元原來的隱含屬性。例如:MOVAX,ES:[DI]

冒號跟在段寄存器ES之后,表示段寄存器的偏移地址由DI指定。2)字節(jié)分離運(yùn)算符LOW和HIGH

用于獲得一個數(shù)值或表達(dá)式的低位或高位字節(jié)。例如:

DATAXEQU1234HMOVAL,LOWDATAXMOVAH,HIGHDATAX

上述程序中,第一句定義DATAX等于1234H;第二句執(zhí)行LOW表示取DATAX的低位,即將34H送AL;第三句執(zhí)行HIGH表示取DATAX的高位,即將12H送AH。

需要注意的是:在表達(dá)式中可能出現(xiàn)各種運(yùn)算的運(yùn)算符,匯編時都將運(yùn)算出它們的具體的結(jié)果,匯編程序的這個運(yùn)算過程將按照它們的優(yōu)先級別進(jìn)行運(yùn)算,運(yùn)算規(guī)則是:

●先執(zhí)行優(yōu)先級別高的運(yùn)算;●優(yōu)先級別相同的運(yùn)算,按從左到右的順序進(jìn)行;●可以使用各種括號改變運(yùn)算順序。各種運(yùn)算符的優(yōu)先級別見表5-2,為1的優(yōu)先級別最高,為11的優(yōu)先級別最低。優(yōu)先級別運(yùn)算符優(yōu)先級別運(yùn)算符1LENGTH,SIZE,(),[]7EQ,NE,LT,LE,GT,GE2: 8NOT3PTR,OFFSET,SEG,TYPE,THIS9AND4HIGH,LOW10OR,XOR5*,/,MOD,SHL,SHR11SHORT6+,-表5-2運(yùn)算符的優(yōu)先級別

注釋也是一個任選項(xiàng),跟在匯編語句之后,以分號“;”開始,注釋內(nèi)容并不出現(xiàn)在匯編后的機(jī)器代碼中,也不影響匯編程序的功能。一段完整的程序中,注釋是很重要的部分,它用于說明一條指令或一段程序的功能,闡述程序的思路,使程序容易閱讀,特別在模塊化程序設(shè)計(jì)中可通過注釋將各模塊的功能描述出來,大大加強(qiáng)了程序的可讀性。4、注釋返回本章目錄

匯編語言源程序采用分段式結(jié)構(gòu),一個匯編語言源程序由若干個邏輯段組成,每個邏輯段以SEGMENT語句開始,以ENDS語句結(jié)束,整個源程序以END語句結(jié)束。而邏輯段包括數(shù)據(jù)段、堆棧段、代碼段及附加段,要注意任何一個源程序至少必須有一個代碼段和一條作為源程序文件結(jié)束的偽指令END,END后面的標(biāo)號START表示該程序執(zhí)行時的啟動地址。下面給出一個簡單的匯編語言源程序,以便對匯編語言源程序的格式結(jié)構(gòu)有一個大概的了解。5.2匯編語言程序結(jié)構(gòu)5.2.1

源程序DATASEGMENT;定義一個名字為DATA的段

HELLODB‘HELLOWORLD1$’;在DATA

段內(nèi)定義一個字符串變量,并賦值

DATAENDS;DATA段結(jié)束

CODESEGMENT;定義一個名字為

CODE的程序代碼段

ASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AX;給DS賦初值

MOVDX,OFFSETHELLO;取字符串變量的偏移量

MOVAH,9;置字符串顯示功能號

INT21H;DOS功能調(diào)用

MOVDL,ODH;送回車符MOVAH,2;置ASCII碼顯示功能號

INT21HMOVDL,OAH;送換行符

MOVAH,2INT21HMOVAH,4CHINT21H;返回操作系統(tǒng)

CODEENDS;代碼段結(jié)束

ENDSTART;源程序結(jié)束

從上面的匯編語言源程序可以看出,一個匯編語言源程序一般總由若干段組成,這里第一段為數(shù)據(jù)段DATA,它在存儲器中存放用于顯示輸出的數(shù)據(jù);第二段為代碼段CODE,它包括了許多以符號表示的指令,用于實(shí)現(xiàn)數(shù)據(jù)的輸出。

程序運(yùn)行時,在匯編語言源程序中除了執(zhí)行上一章中介紹的指令外,還要執(zhí)行偽指令和宏指令。偽指令又稱偽操作,匯編程序?qū)υ闯绦騾R編時,偽指令本身不會產(chǎn)生可執(zhí)行的機(jī)器指令代碼,它僅僅是告訴匯編程序有關(guān)源程序的某些信息,或者用來說明內(nèi)存單元的用途,即偽指令在匯編過程中是由匯編程序執(zhí)行的指令,它可以用來進(jìn)行數(shù)據(jù)定義、符號定義、段定義、過程定義及程序命名及結(jié)束等主要操作。5.2.2

偽指令

數(shù)據(jù)定義偽指令用于定義變量的類型、給存儲器賦初值或給變量分配存儲單元。常用的數(shù)據(jù)定義偽指令有DB、DW、DD等。一般格式為:

[標(biāo)號]偽指令助記符數(shù)據(jù)表達(dá)式方括號中的標(biāo)號為任選項(xiàng),通常使用符號地址表示。數(shù)據(jù)表達(dá)式可以包含多個數(shù)據(jù),它們之間用逗號分隔開。數(shù)據(jù)定義偽指令助記符有以下三種:

DB定義變量類型為字節(jié)(BYTE),DB后面的每個操作數(shù)占一個字節(jié)單元。

DW定義變量類型為字(WORD),DW后面的每個操作數(shù)占一個字單元,即兩個字節(jié)單元。在內(nèi)存中,低字節(jié)在前,高字節(jié)在后。

DD定義變量類型為雙字(DWORD),DD后面的每個操作數(shù)占兩個字單元,即四個字節(jié)單元。在內(nèi)存中,低位字在前,高位字在后。1、數(shù)據(jù)定義偽指令

這些數(shù)據(jù)定義偽操作可以把數(shù)據(jù)項(xiàng)存入指定的存儲單元,或分配存儲單元空間。例如:

R1DB0DH ;定義R1單元的數(shù)值為0DHR2DB? ;定義R2單元預(yù)留一個字節(jié)的存儲空間

R3DB1,2,3;定義R3開始的3個單元的數(shù)值為

01H,02H,03HR4DW5DUP(?);定義R4預(yù)留5個字的存儲空間

R5DB‘GOOD!’;定義R5為字符串,其存儲單元數(shù)值為47H,4FH,4FH,44H,

;21H

上例說明,數(shù)據(jù)表達(dá)式除了可以是二進(jìn)制、十進(jìn)制、十六進(jìn)制的常數(shù),也可以是表達(dá)式及字符串,還可以是問號“?”,它僅給變量保留相應(yīng)的存儲單元,而不給變量賦初值。當(dāng)相同的操作數(shù)重復(fù)出現(xiàn)或要保留多個存儲單元時,可用重復(fù)操作符號DUP表示,重復(fù)次數(shù)由DUP之前的數(shù)字決定。經(jīng)過匯編偽指令,數(shù)據(jù)在存儲單元中的分配如圖5-1所示。R1ODHR2﹎R301H02H03H﹎﹎﹎﹎﹎﹎﹎R4R5

47H4FH4FH44H21H保留5個字的存儲空間,即10個字節(jié)圖5-1

偽指令執(zhí)行后數(shù)據(jù)區(qū)的分配情況

由圖5-1可見,存儲單元中的數(shù)據(jù)均由補(bǔ)碼表示;對于多字節(jié)的數(shù)據(jù)分配,高字節(jié)存放在高地址單元,低字節(jié)存放在低地址單元;對于字符串存儲單元存放的是相應(yīng)的ASCII碼;對于變量或標(biāo)號存儲單元存放的是相應(yīng)的地址偏移量。另外,在偽指令中還可以對重復(fù)子句進(jìn)行嵌套,例如:BUFFERDB2,2DUP(1,2DUP(2,3))

該偽指令匯編后的數(shù)據(jù)分配情況如圖5-2所示。03HBUFFER02H01H02H03H02H01H02H03H02H03H圖5-2

偽指令執(zhí)行后數(shù)據(jù)區(qū)的分配情況

這里的符號是指變量名、標(biāo)號名、過程名、指令助記符和寄存器名,符號定義偽指令用于給一個符號重新命名或定義新的類型屬性。

(1)EQU偽指令

EQU偽指令將表達(dá)式的值賦予一個名字,這是一個等值語句。定義以后可以用這個名字來代替對應(yīng)的表達(dá)式。表達(dá)式可以是一個常數(shù)、符號、數(shù)值、表達(dá)式或地址表達(dá)式,EQU偽指令的格式如下:名字EQU

表達(dá)式2、符號定義偽指令EQU偽指令可以使程序更加簡練。如果源程序中需要多次引用某個表達(dá)式,可以用一個比較簡短的名字通過EQU偽指令來代表這個表達(dá)式。如果將來需要修改表達(dá)式,只需修改EQU語句中的表達(dá)式,而不必修改多處,便于程序的維護(hù)。需要注意的是,EQU偽指令不允許對同一符號重復(fù)定義,即同一源程序中,用EQU定義過的變量,不能再定義其他值。例如:

FIVEEQU5;FIVE賦值為5NINEEQUFIVE+4;NINE定義為數(shù)值表達(dá)式,其值為9REGSEQUSI;指定寄存器SI的名字為REGSADDREQUTABLE;將標(biāo)號TABLE賦值到ADDR

(2)等號(=)偽指令等號(=)偽指令的功能與EQU偽指令相仿,區(qū)別在于它可以對同一個名字重復(fù)定義。其偽指令格式如下:名字=表達(dá)式利用等號(=)偽指令可以使程序設(shè)計(jì)更加靈活。例如:

TABLE=1MOVAX,TABLERRRR:ADDAX,1?TABLE=TABLE+1MOVAX,TABLECMPAX,100JNERRRR?

上例中,標(biāo)號TABLE被定義了不止一次,每循環(huán)一次它的數(shù)值都會變化。

段定義偽指令在匯編語言源程序中定義邏輯段,提供了構(gòu)造程序的手段。常用的段定義偽指令有ASSUME、SEGMENT和ENDS等。(1)SEGMENT和ENDS用SEGMENT和ENDS偽指令可以將程序分成多個段,用于定義一個邏輯段,給邏輯段賦予一個段名,并在后面的任選項(xiàng)中給出這個邏輯段的其他特性,如定義類型、組合類型和類別。其偽指令格式如下:段名SEGMENT[定位類型][組合類型][‘類別’]?(段定義體)段名ENDS3、段定義偽指令SEGMENT偽指令定義一個邏輯段的開始,ENDS偽指令則表示一個邏輯段的結(jié)束,這兩個偽指令總是成對出現(xiàn)。前面的段名是該邏輯段的標(biāo)識符,是用來確定該邏輯段在存儲器中的首地址的,不可缺省,而且必須一致。兩個偽指令語句之間的部分是邏輯段的內(nèi)容,匯編語言的邏輯段包括代碼段、數(shù)據(jù)段和堆棧段等,代碼段主要包含程序指令和某些偽指令;數(shù)據(jù)段用于定義數(shù)據(jù)和存儲單元;堆棧段主要為堆棧操作預(yù)留出存儲空間。

SEGMENT偽指令后面可以有三個任選項(xiàng)—“定位類型”、“組合類型”、“類別”,它們用來指示匯編程序和連接程序,如何確定段的邊界,如何進(jìn)行段的組合,以及控制段的裝入順序。在簡單匯編語言源程序中一般選用缺省方式,常用于多模塊的程序設(shè)計(jì)中。如果出現(xiàn),三者的順序必須符合格式中的規(guī)定,不能顛倒。

1)定位類型:定位類型任選項(xiàng)是告訴匯編程序如何確定邏輯段的邊界在存儲器中的開始位置,定位類型有四種:

BYTE:表示邏輯段邊界可以從任何一個字節(jié)開始,段與段之間無空隙。這樣,該邏輯段可以緊接在前一個邏輯段的后面。

WORD:表示邏輯段邊界從字地址開始,段與段之間的空隙最多只有一個字節(jié)。這樣該邏輯段的起始地址必須是偶數(shù)。

PARA:表示邏輯段邊界從節(jié)地址開始,16個字節(jié)稱為一個節(jié)。段地址為16的倍數(shù),即XXX0H,這樣段與段之間空隙最多為15個字節(jié)。如果省略定位類型選項(xiàng),匯編語言程序默認(rèn)該邏輯段為PARA。

PAGE:表示邏輯段邊界地址從頁邊界開始。256個字節(jié)成為一個頁,則段地址為256的倍數(shù),即XX00H,這樣段與段之間空隙最多為255個字節(jié)。

2)組合類型:SEGMENT偽指令的第二個任選項(xiàng)是組合類型,在滿足定位類型的前提下,它告訴連接程序,裝入存儲器時各個邏輯段如何進(jìn)行組合。組合類型有6種。

NONE:此項(xiàng)為不組合,是組合類型的缺省選擇,此時連接程序認(rèn)為這個邏輯段是不組合的,即使兩個段有相同的類別名,也作為不同的邏輯段分別裝入內(nèi)存。

PUBLIC:匯編程序連接時,對于不同程序模塊中的邏輯段,只要具有相同的類別名,就把這些段順序連接成一個邏輯段裝入內(nèi)存,共用一個寄存器,所有段的偏移地址都要變?yōu)橄鄳?yīng)組合段的偏移量。

STACK:表示該段為堆棧段的一部分,此時編譯程序把所有同名段連接成一個連續(xù)的堆棧段,裝入SS段寄存器,用段內(nèi)的最大偏移地址初始化SP。COMMON:該組合類型產(chǎn)生一個覆蓋段。模塊連接時,如果有相同的類別名,則都從同一個地址開始裝入,因而連接的邏輯段將發(fā)生覆蓋。連接以后段的長度等于原來最長的路段的長度,覆蓋部分的內(nèi)容是最后一個邏輯段的內(nèi)容。

MEMORY:表示該段在存儲器中應(yīng)定位在所有其他段的最高地址處。如果有多個段使用MEMORY,則只把第一個遇到的段當(dāng)作MEMORY處理,其余的段均按PUBLIC處理。

AT:表示該段定位在表達(dá)式所指示的位置上。

3)類別名:類別名必須用單引號括起來,用于控制段的裝入順序。類別名可由程序設(shè)計(jì)人員自己選定任何字符串組成,但它不能再作為程序的標(biāo)號,變量名或其他定義的符號。在連接處理時,LINK程序把類別名相同的所有段存放在連續(xù)的存儲區(qū)內(nèi)。

例如,下面就是一個分段結(jié)構(gòu)的源程序框架:

STACK1SEGMENTPARASTACK‘STACK1’;定義堆棧段1?STACK1ENDSDATA1SEGMENTPARA‘DATA1’;定義數(shù)據(jù)段1?DATA1ENDSSTACK2SEGMENTPARA‘STACK2’;定義堆棧段2

?STACK2ENDSDATA2SEGMENTPARA‘DATA2’;定義數(shù)據(jù)段2?DATA2ENDSCODESEGMENTPARAMEMORY;定義代碼段

ASSUMECS:CODE,DS:DATA1,SS:STACK1;

指定段寄存器

BEGIN:…

?CODEENDSENDSTART

(2)ASSUME

指示匯編程序指定段所使用的寄存器,即將段寄存器與某個邏輯段建立起對應(yīng)關(guān)系,該偽指令不產(chǎn)生任何目標(biāo)代碼。其格式如下:

ASSUNE

段寄存器名:段名[,段寄存器名:段名]

其中段寄存器名是指四個段寄存器CS、SS、DS、ES中的一個,但要注意,程序代碼段只能用CS作寄存器,堆棧段只能用SS作段寄存器。段名是指邏輯段的名字。在一個源程序中,如果沒有另外的ASSUME偽指令重新設(shè)置,原有的ASSUME語句的設(shè)置一直有效。需要注意的是,ASSUME偽指令只是告訴匯編程序段寄存器與邏輯段的關(guān)系,并沒有給段寄存器賦予實(shí)際的初值。若要給段寄存器賦值,可參考下面程序:CODESEGMENT;定義代碼段

ASSUMECS:CODE,DS:DATA1,SS:STACK1;指定段寄存器

MOVAX,DATA1MOVDS,AX;初始化段寄存器DSMOVAX,STACK1MOVSS,AX;初始化堆棧段寄存器SS

?CODEENDS

過程又稱子程序,它是程序的一部分,可以被程序調(diào)用,當(dāng)過程中的指令執(zhí)行完后,返回程序調(diào)用點(diǎn),調(diào)用過程的指令是CALL,從過程返回的指令為RET。程序設(shè)計(jì)中,我們常常把具有一定功能的程序段設(shè)計(jì)成一個子程序,匯編程序用“過程”來構(gòu)造子程序。過程定義偽指令的格式如下:

過程名PROC[NEAR/FAR];NEAR與FAR只選一個,或缺省

?(過程體)

過程名ENDP

其中,過程名不能省略,過程名也就是子程序的程序名,可以通過CALL指令調(diào)用,它類同于一個標(biāo)號的作用,具有三個屬性:段、偏移量和類型。類型可以選擇NEAR或FAR,如果沒有選擇距離類型,則默認(rèn)為NEAR。用PROC表示過程的開始,ENDP表示過程的結(jié)束,它們應(yīng)成對出現(xiàn),并使用同一個過程名。一個過程應(yīng)該寫在某一個邏輯段內(nèi)。例如:4、過程定義偽指令CODESEGMENTASSUMECS:CODEDISCHPROCNEAR;定義一個過程(段內(nèi)調(diào)用屬性)

MOVAH,2INT21HDISCHENDP;過程結(jié)束

START:MOVDL,30HCALLDISCH;調(diào)用過程(屬段內(nèi)調(diào)用)

MOVDL,‘A’CALLDISCH;調(diào)用過程(屬段內(nèi)調(diào)用)

MOVAH,4CHINT21H;返回到DOSCODEENDSENDSTART

注意,若過程調(diào)用為段間調(diào)用時,則在調(diào)用過程時要將返回地址的段地址和偏移量都壓入堆棧。

匯編程序內(nèi),為了指定下一個數(shù)據(jù)或指令在相應(yīng)段中的偏移量,匯編程序使用了一個定位偽指令。其格式為:

ORG

表達(dá)式它表示把表達(dá)式的值賦給當(dāng)前位置計(jì)數(shù)器$。例如:5、定位偽指令ORG和當(dāng)前位置計(jì)數(shù)器$DATASEGMENTORG20H;設(shè)置位置計(jì)數(shù)器$為20HD1DB12H,13H;12H,13H從偏移量為20H

處開始存放

ORG$+01H;設(shè)置位置計(jì)數(shù)器$為$+01HD2DB61H,62H,63H;61H,62H,63H從偏移量為21H處開始存放

DATAENDSCODESEGMENTASSUMECS:CODE,…ORG100H;設(shè)置位置計(jì)數(shù)器$為100HSTART:MOVAX,DATA;BEGIN從偏移量為

100H處開始存放?

CODEENDSENDSTART

標(biāo)題偽指令TITLE用于給程序設(shè)置一個標(biāo)題,列表文件中每一頁的第一行都會顯示這個標(biāo)題,它是用戶任意選定的字符串,但是字符的個數(shù)不能超過6b0,用END標(biāo)識源程序模塊的結(jié)束,其后可跟程序啟動標(biāo)號或過程名,用于指明程序的啟動地址,系統(tǒng)根據(jù)這個地址初始化CS。其格式為:

TITLE

字符串

END[啟動標(biāo)號]6、標(biāo)題偽指令TITLE

告訴匯編程序任務(wù)到此結(jié)束,其后可跟程序啟動標(biāo)號或過程名,用于指明程序執(zhí)行時第一條指令的地址。其格式為:

END

表達(dá)式7、源程序結(jié)束偽指令

匯編語言中,如果源程序中需要多次重復(fù)使用同一組指令,為了簡化匯編語言源程序的書寫,縮短主程序的長度,可以將這組指令定義為一個“宏指令”,以后需要時,可以按宏指令名來引用,這比子程序更靈活、更簡便。宏匯編程序MASM提供了豐富的宏操作偽指令語句,下面介紹幾種常用的宏指令語句。5.2.3宏指令

宏定義的一般格式為:宏指令名MACRO

[形式參數(shù)1,形式參數(shù)2,…]?(宏定義體)

ENDM1、宏定義與宏調(diào)用

其中,宏定義符MACRO和宏結(jié)束符ENDM必須成對出現(xiàn),其間的宏定義體就是用宏指令名來代替的指令組。形式參數(shù)用于向宏定義體傳送參數(shù),在宏調(diào)用時代入實(shí)際參數(shù),這使宏指令具有更強(qiáng)的通用性。宏調(diào)用格式為:

宏指令名[實(shí)際參數(shù)1,實(shí)際參數(shù)2,…]

注意,這里的實(shí)際參數(shù)可以是常數(shù)、寄存器、存儲單元名以及地址表達(dá)式等。實(shí)際參數(shù)的數(shù)目可以和形式參數(shù)的數(shù)目不一致,當(dāng)實(shí)際參數(shù)多于形式參數(shù)時,多余的實(shí)際參數(shù)將被忽略;當(dāng)實(shí)際參數(shù)少于形式參數(shù)時,多余的形式參數(shù)為空。匯編時,MASM將對每個宏調(diào)用進(jìn)行展開,即將宏指令名用相應(yīng)的宏定義體中的指令組代替,用實(shí)際參數(shù)代替形式參數(shù),并在指令組前加一個“+”號。例如:SHIFTMACRO;宏定義

MOVCL,4SALAL,CL;宏定義體

ENDM?MOVAL,[DX]ADDAL,[SI]SHIFT;宏調(diào)用

MOV[BX].AL

匯編后,產(chǎn)生如下的代碼:?

MOVAL,[DX]

+ADDAL,[SI]

+MOVCL,4SALAL,CLMOV[BX].AL?

若既要使左移次數(shù)可改變,又要能使用不同的寄存器進(jìn)行移位,就要引入形式參數(shù),用X來代替左移次數(shù),用Y來代替移位的寄存器。宏定義如下頁:SHIFTMACROX,YMOVCL,XSALY,CLENDM

如宏調(diào)用為

SHIFT4,ALSHIFT8,BX

則在匯編時,會產(chǎn)生如下代碼:

+MOVCL,4+SALAL,CL+MOVCL,8+SALBX,CL

另外,形式參數(shù)還可以是操作碼,這樣連運(yùn)算也可以用不同的運(yùn)算了。例如:宏定義為:

SHIFTMACROX,Y,ZMOVCL,XZY,CLENDM

若宏調(diào)用為:

SHIFT5,DX,SHL

匯編后得

+MOVCL,5+SHLDX,CLPURGE的用途是取消已有的宏定義。匯編程序允許所定義的宏指令名與機(jī)器指令的助記符或偽指令的名字相同,匯編程序優(yōu)先考慮宏指令的定義。也就是說,與宏指令同名的指令助記符或偽指令原來的含義失效。用偽指令PURGE取消宏指令定義后,可恢復(fù)這些機(jī)器指令或偽指令的原來含義。對一個宏指令重新定義時,也必須用偽指令PURGE取消原來的宏定義。其格式如下:

PURGE

宏指令名,宏指令名,…2、宏取消偽指令PURGE

重復(fù)宏體所包含的語句,重復(fù)次數(shù)由表達(dá)式的值決定。該語句與宏定義不同,宏定義可在程序不同地方多次引用,而重復(fù)宏指令只能在程序某個地方重復(fù)語句塊。其格式如右:3、重復(fù)宏指令REPTREPT

表達(dá)式宏體ENDM返回本章目錄

程序設(shè)計(jì)是指為計(jì)算機(jī)編寫能夠接受并執(zhí)行的,并具有實(shí)際意義的語句序列。匯編語言程序設(shè)計(jì)需要經(jīng)過幾個階段,但問題的復(fù)雜程度不同編程者的經(jīng)驗(yàn)不同,使得程序設(shè)計(jì)的具體過程也會有所不同。一般來說,在實(shí)際的程序設(shè)計(jì)中常常要經(jīng)過以下幾個階段:

1、分析題目對給出的題目進(jìn)行全面細(xì)致的了解和分析。了解程序應(yīng)完成的任務(wù)、應(yīng)用的場合、硬件環(huán)境、人機(jī)接口要求、輸入輸出信息等,這是編程的準(zhǔn)備階段。5.3匯編語言程序設(shè)計(jì)

2、建立數(shù)學(xué)模型在分析問題和明確要求的基礎(chǔ)上,建立數(shù)學(xué)模型。所謂數(shù)學(xué)模型是將物理過程或某種工作狀態(tài)用數(shù)學(xué)表達(dá)式寫出。

3、確定算法和處理方案數(shù)學(xué)模型建立后,要研究具體的算法,也就是適合于計(jì)算機(jī)使用的計(jì)算方法,并對算法進(jìn)行優(yōu)化。一個大的程序往往需要多人協(xié)同工作,必須采用模塊化的設(shè)計(jì)方法,根據(jù)任務(wù)的要求,把總?cè)蝿?wù)分成若干個獨(dú)立的模塊,對各個模塊進(jìn)行程序設(shè)計(jì)。模塊劃分的好壞與編程者的經(jīng)驗(yàn)及對任務(wù)的理解程度有關(guān),應(yīng)力求做到模塊劃分合理。

4、畫出流程圖流程圖是對算法和整個程序結(jié)構(gòu)的描述,它以圖形的方式把解決問題的先后次序形象地描述出來,也可以準(zhǔn)確地描述各種程序結(jié)構(gòu)之間的關(guān)系,這有利于程序的編寫和調(diào)試。對于復(fù)雜的程序,一定要先畫出流程圖,這樣才能從全局的角度來規(guī)劃程序結(jié)構(gòu)。

開始結(jié)束框:用于表示一個程序段的開始與結(jié)束。如圖5-3(a)所示。

執(zhí)行框:用矩形框表示,用于描述一個具體的執(zhí)行動作,如一個算式、一個操作等。一般用幾個框來描述執(zhí)行動作,在不致于引起混淆的情況下,用一個框也可描述多個執(zhí)行動作。如圖5-3(b)所示。

判斷框:根據(jù)某一個或幾個條件,實(shí)現(xiàn)分支轉(zhuǎn)移,如圖5-3(c)所示。

遠(yuǎn)接框:用于表示流程圖中較遠(yuǎn)處的連接,簡單程序中一般不會出現(xiàn),如圖5-3(d)所示。

指向線:用帶箭頭的引線指示程序的走向。開始結(jié)束a)開始結(jié)束框處理過程b)執(zhí)行框條件條件c)判斷框d)判斷框開關(guān)條件…圖5-3程序流程圖的基本元素5、編制程序編制程序時,應(yīng)先分配好存儲空間及所使用的寄存器,根據(jù)流程圖及算法編寫程序。應(yīng)注意的是,編寫程序要簡潔,注意提高程序的可讀性。

6、上機(jī)調(diào)試程序編寫完成之后,要進(jìn)行上機(jī)調(diào)試。在調(diào)試過程中往往會碰到語法錯誤,連接錯誤等問題,這時需要及時修改源程序,再反復(fù)調(diào)試。對于復(fù)雜的程序一般分塊解決,也就是先對獨(dú)立的模塊進(jìn)行單獨(dú)調(diào)試,最后將整個程序連接在一起調(diào)試。

7、試運(yùn)行程序調(diào)試成功后,并不代表程序設(shè)計(jì)整個過程完成,試運(yùn)行程序及分析程序各模塊運(yùn)行結(jié)果是檢驗(yàn)程序是否達(dá)到要求的最后環(huán)節(jié)。有時程序調(diào)試通過了,但在執(zhí)行過程中,卻不能達(dá)到原設(shè)計(jì)要求,這時還要動態(tài)地分析程序,從分析問題開始,對源程序進(jìn)行修改,再對程序進(jìn)行調(diào)試,最終達(dá)到設(shè)計(jì)要求。注意,程序的使用環(huán)境于操作界面,要能滿足用戶的要求。

順序結(jié)構(gòu)是解決簡單問題的一種程序設(shè)計(jì)方法,它按指令存放的先后次序執(zhí)行一系列操作。程序中沒有分支、不循環(huán)、不轉(zhuǎn)移,一直執(zhí)行到最后一條指令,這種程序也稱為直線程序。順序結(jié)構(gòu)程序在設(shè)計(jì)上比較簡單,實(shí)際應(yīng)用中,完全由順序結(jié)構(gòu)構(gòu)成的程序很少,但它作為一個程序的局部卻廣泛存在于每個復(fù)雜程序中,它是設(shè)計(jì)復(fù)雜程序的基礎(chǔ)。

【例5-1】求表達(dá)式Z=(10X+4Y)/2的值(X、Y為字節(jié)型變量,Z為字型變量)。解:本題為典型的順序結(jié)構(gòu)。在數(shù)據(jù)段設(shè)定X、Y的數(shù)據(jù)是66H、35H,采用左移的方法完成10X、4Y,用右移的方法完成除2的計(jì)算。程序如下頁:5.3.1順序結(jié)構(gòu)DATASEGMENT;定義數(shù)據(jù)段

XDB66HYDB35H;定義X、Y為字節(jié)變量

ZDW?;定義Z為字變量DATAENDCODESEGMENT;定義代碼段

ASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AX;對DS賦值

MOVAL,XSHLAX,1;AX=2XMOVBX,AXSHLBX,1;BX=4XSHLBX,1;BX=8XADDBX,AX;BX=2X+8XMOVAH,0MOVAL,YSHLAX,1;AX=2YSHLAX,1;AX=4YADDBX,AX;AX=10X+4YSHRBX,1;AX=(10X+4Y)/2MOVZ,BX;將結(jié)果存入ZMOVAH,4CH;結(jié)束進(jìn)程,返回操作系統(tǒng)

INT21HCODEENDSENDSTART

注意:上例沒有使用堆棧段,所以程序中沒有給SS、SP賦值,若使用了堆棧段,必須給堆棧段賦值。該程序中沒有結(jié)果顯示的程序段,程序運(yùn)行后屏幕上沒有輸出顯示,可以執(zhí)行DEBUG程序觀察其運(yùn)行結(jié)果。

分支結(jié)構(gòu)是對問題的處理方法有兩種以上不同選擇時,根據(jù)不同條件轉(zhuǎn)向不同程序段執(zhí)行的程序設(shè)計(jì)方法。分支結(jié)構(gòu)要求程序先進(jìn)行不同條件的判斷,然后依據(jù)判斷結(jié)果用控制轉(zhuǎn)移指令,將程序的執(zhí)行流程轉(zhuǎn)移到相應(yīng)的分支上去,判斷一次只可能有一路分支被選擇。分支程序結(jié)構(gòu)有兩路分支與多路分支兩種形式。兩路分支完成對兩種情況的選擇處理,每次對條件的判斷都會有兩種可能的結(jié)果:T(真或條件滿足)、F(假或條件不滿足),此時可以根據(jù)判斷的不同結(jié)果決定執(zhí)行不同的程序段,如圖5-4(a),也可以根據(jù)判斷結(jié)果的不同決定執(zhí)行或不執(zhí)行某段程序段,如圖5-4(b)。多路分支則完成對多種情況的選擇處理,相當(dāng)于兩路分支的嵌套結(jié)構(gòu),如圖5-4(c)。5.3.2

分支結(jié)構(gòu)條件程序段1程序段2TFa)條件程序段FTb)條件1條件2條件n程序段n+1程序段n程序段1程序段2TFTFTFc)圖5-4分支程序結(jié)構(gòu)圖【例5-3】設(shè)計(jì)單個字符比較程序。兩個字符相同時,顯示YES;不同時,顯示NO。解:根據(jù)題目要求,在數(shù)據(jù)段設(shè)定兩個字節(jié)D1、D2存放要進(jìn)行比較的字符,設(shè)定從MESS1、MESS2開始的單元存放比較結(jié)果的字符串YES、NO。程序代碼段主要是從D1、D2中取出兩字符,進(jìn)行比較,若A大于B,則從MESS1中取出YES字符串顯示,否則,從MESS2中取出NO字符串顯示。一般先用序流程圖描述解決問題的思路,程序流程圖如圖5-5所示。程序如下頁:圖5-5例5-3程序流程圖A=B?顯示YES顯示NOTFD1←AD2←B開始結(jié)束DATA1SEGMENTD1DB‘A’;D1單元存字符AD2DB‘B’;D2單元存字符BMESS1DB‘YES’,‘$’;從MESS1開始的單元存結(jié)果提示字符串YESMESS2DB‘NO’,‘$’;從MESS1開始的單元存結(jié)果提示字符串NODATA1ENDSSTACK1SEGMENTPARASTACKDW20DUP(0)

STACK1ENDSCODESEGMENTASSUMECS:CODE,DS:DATA1,SS:STACK1START:MOVAX,DATA1MOVDS,AXMOVAL,D1MOVBL,D2CMPAL,BL;比較兩個字符

JNEC1;不等,轉(zhuǎn)C1LEADX,MESS;相等,調(diào)字符串‘YES’JMPC2;轉(zhuǎn)移到C2C1:LEADX,MESS2;調(diào)字符串‘NO’C2:MOVAH,09HINT21HMOVAH,4CHINT21HCODEENDSENDSTART

本例中,進(jìn)行比較的A、B兩個字符,所以運(yùn)行程序后應(yīng)顯示NO。

循環(huán)結(jié)構(gòu)按給定的條件重復(fù)做一系列的操作,直到條件滿足為止。循環(huán)結(jié)構(gòu)可以在解決復(fù)雜問題時,縮短程序代碼,提高編程效率。例如求內(nèi)存中連續(xù)1000個數(shù)的累加和,若采用順序結(jié)構(gòu)程序設(shè)計(jì),僅加法指令就必須用999條,若采用循環(huán)結(jié)構(gòu)程序設(shè)計(jì),只要設(shè)定循環(huán)的次數(shù)為999次,用有限的幾條指令就能完成,極大地縮短了程序,提高了編程效率。循環(huán)程序一般由循環(huán)初始狀態(tài)設(shè)置、循環(huán)體和循環(huán)控制三個部分。

循環(huán)初始狀態(tài):是循環(huán)的準(zhǔn)備部分,主要給地址指針寄存器設(shè)置初始值、設(shè)置循環(huán)計(jì)數(shù)器初值、給累加器、進(jìn)位標(biāo)志清零等。

循環(huán)體:包括循環(huán)的工作部分和修改部分,工作部分就是根據(jù)具體要求設(shè)計(jì)的程序段,修改部分是對各種計(jì)數(shù)器、累加器、進(jìn)位標(biāo)志的增量或減量修改,以配合工作部分的程序執(zhí)行。5.3.3循環(huán)結(jié)構(gòu)

循環(huán)控制:是循環(huán)的核心部分,通過測試循環(huán)的條件,控制循環(huán)程序的運(yùn)行和結(jié)束。循環(huán)控制部分分計(jì)數(shù)控制法和條件控制法兩種。計(jì)數(shù)控制法適用于循環(huán)次數(shù)是可以預(yù)先確定的情況,先執(zhí)行循環(huán)體操作,再根據(jù)循環(huán)次數(shù)判斷循環(huán)是否結(jié)束,即“先執(zhí)行,后判斷”。如果循環(huán)的條件一開始就達(dá)到循環(huán)結(jié)束的條件,循環(huán)體至少也要執(zhí)行一次操作,結(jié)構(gòu)圖如圖5-8(b)所示。計(jì)數(shù)控制法的循環(huán)結(jié)構(gòu)又分正計(jì)數(shù)控制法和倒計(jì)數(shù)控制法,正計(jì)數(shù)控制法是將計(jì)數(shù)器的初值設(shè)定為0,每執(zhí)行一次循環(huán),計(jì)數(shù)器加1,然后與規(guī)定的循環(huán)次數(shù)進(jìn)行比較,若未達(dá)到循環(huán)次數(shù)則繼續(xù)循環(huán)執(zhí)行程序,否則循環(huán)結(jié)束。倒計(jì)數(shù)控制法是將計(jì)數(shù)器的初值設(shè)定為循環(huán)次數(shù),每執(zhí)行一次循環(huán),計(jì)數(shù)器減1,直至計(jì)數(shù)器為0時循環(huán)結(jié)束。注意這種結(jié)構(gòu)一般以循環(huán)次數(shù)作為判斷條件,循環(huán)次數(shù)在循環(huán)初始狀態(tài)時已進(jìn)行了設(shè)置,是一個固定的數(shù)值。條件控制法循環(huán)的次數(shù)無法預(yù)先確定,先判斷循環(huán)的條件是否滿足,若條件滿足則執(zhí)行循環(huán),即“先判斷,后執(zhí)行”。如果循環(huán)的條件一開始就不成立,循環(huán)體就不會被執(zhí)行,結(jié)構(gòu)圖如圖5-8(a)所示。圖5-8循環(huán)程序結(jié)構(gòu)圖循環(huán)條件循環(huán)初始設(shè)置循環(huán)體不滿足滿足循環(huán)初始設(shè)置循環(huán)體循環(huán)條件滿足不滿足a)條件控制法b)記數(shù)控制法

在一個程序設(shè)計(jì)中,常常會出現(xiàn)不同的地方需要多次使用相同的某段程序代碼的情況,如果在每個需要的地方都編寫這一段程序代碼,當(dāng)程序裝入內(nèi)存時會占用很多的存儲空間,造成不必要的資源開銷,另外重復(fù)編寫程序也增加了程序設(shè)計(jì)人員的工作量,并使程序復(fù)雜化,不便于閱讀和檢查。因此常將這一段公用的程序代碼單獨(dú)編制成一段程序代碼,作為一個獨(dú)立的程序模塊處理,使用時就轉(zhuǎn)移到這個公用程序段上,該程序段執(zhí)行完畢后,又返回到原來的程序位置繼續(xù)運(yùn)行。這個單獨(dú)編制的獨(dú)立公用程序段稱為子程序,也稱過程,轉(zhuǎn)移到子程序的過程稱為調(diào)用子程序。子程序的設(shè)計(jì)是程序設(shè)計(jì)中最重要的方法之一。5.3.4

子程序1、子程序的定義子程序由偽指令PR0C和ENDP定義。子程序和調(diào)用程序在同一代碼段時,子程序設(shè)置為NEAR屬性(或缺省);子程序和調(diào)用程序不在同一代碼段時,子程序設(shè)置為FAR屬性。子程序定義格式如下:

子程序名PROC

屬性(NEAR或FAR)子程序體子程序名ENDP

2、子程序的調(diào)用和返回子程序的調(diào)用和返回用指令CALL和RET實(shí)現(xiàn)。一般CALL指令在主程序中,它實(shí)質(zhì)上是一條特殊的帶返回的無條件轉(zhuǎn)移指令,由于轉(zhuǎn)移后要返回,所以要進(jìn)行斷點(diǎn)保護(hù)。而RET指令則在被調(diào)用子程序的末尾,在子程序執(zhí)行完后返回到CALL指令的下一條指令繼續(xù)執(zhí)行主程序,調(diào)用與返回指令的使用如圖5-11所示。當(dāng)然,子程序還可以調(diào)用其他子程序或自身。CALL(調(diào)用)CALL(調(diào)用)主程序子程序RET(返回)圖5-11

子程序的調(diào)用和返回3、現(xiàn)場信息的保護(hù)和恢復(fù)由于子程序執(zhí)行時可能要使用某些寄存器,而主程序在調(diào)用子程序的前后也可能正在使用這些寄存器,此時主程序和子程序使用的寄存器就可能發(fā)生沖突,所以必須考慮現(xiàn)場信息的保護(hù)和恢復(fù)。這個過程可以在主程序中完成。例如,主程序中正在使用AX、BX和CX寄存器,子程序需要使用BX、CX寄存器,這時就要將BX、CX的內(nèi)容壓入堆棧,待子程序返回后,再從堆棧中恢復(fù)BX、CX的內(nèi)容。在主程序中的調(diào)用子程序的格式為:

?

PUSHBXPUSHCXCALLSUBRPOPCXPOPBX?

現(xiàn)場信息的保護(hù)和恢復(fù)也可在子程序中進(jìn)行,這種情況下可以根據(jù)子程序要使用的寄存器來確定哪些寄存器。如子程序要用到BX、CX,這時要在進(jìn)入子程序后馬上把BX、CX壓棧,在結(jié)束子程序前,將BX、CX恢復(fù)。子程序中信息保護(hù)的格式為:

SUBRPROCPUSHBXPUSHCX?;子程序功能段

POPCXPOPBXRETSUBRENDP

注意,出棧與壓棧應(yīng)采用相反的順序,即“先進(jìn)后出”。4、參數(shù)傳遞子程序的設(shè)計(jì)要求有一定的通用性,要求調(diào)用子程序時,經(jīng)常要求主程序?qū)?shù)傳遞給子程序,從子程序返回時,子程序往往要將處理結(jié)果傳遞回主程序。這就是主程序和子程序之間參數(shù)的傳送問題,參數(shù)傳遞的主要方法有以下三種:(1)利用存儲器傳遞參數(shù)這種參數(shù)傳遞方式要求主程序與子程序在同一模塊中,子程序和主程序都可以直接訪問模塊中的參數(shù)。(2)利用寄存器傳遞參數(shù)這種參數(shù)傳遞方式適用于傳遞參數(shù)較少的情況,通常是主程序?qū)?shù)直接置入某寄存器中,而子程序則使用該寄存器中的參數(shù);或子程序?qū)⑻幚斫Y(jié)果存入某寄存器,返回給主程序后使用。

(3)利用堆棧傳遞參數(shù)這是一種通過堆棧這一公共存儲區(qū)中進(jìn)行參數(shù)傳遞的方法,傳遞參數(shù)較多時傳遞數(shù)據(jù)的結(jié)構(gòu)比較清晰。主程序?qū)?shù)依次壓入堆棧,而子程序則按相反的順序從堆棧中取出參數(shù)處理;或由子程序向主程序回傳參數(shù)。(4)利用公用數(shù)據(jù)區(qū)傳遞參數(shù)這種方式是在內(nèi)存中開辟一個地址表,主程序和子程序?qū)⒁獋鬟f的參數(shù)存放在地址表里,并將地址表的首地址經(jīng)BX寄存器傳送給子程序,子程序按首地址訪問地址表。另外,當(dāng)使用堆棧較多時,最好設(shè)立自己的堆棧區(qū),并且給SS和SP賦值。同時要注意入棧與出棧的順序,先入棧的信息最后出棧。DOS系統(tǒng)設(shè)置了DOS和BIOS兩組中斷程序供調(diào)用,可以完成鍵盤輸入、信息顯示、存儲管理、文件操作等服務(wù)。BIOS為系統(tǒng)中的輸入輸出設(shè)備提供軟件接口,使用戶在不了解硬件特性的情況下,也能通過調(diào)用其程序使用這些設(shè)備,它們駐留在系統(tǒng)ROM內(nèi)存區(qū),入口安排在中斷向量表中,系統(tǒng)調(diào)用的中斷類型號為05~1FH(關(guān)于中斷的詳細(xì)內(nèi)容在第8章介紹)。DOS提供了更容易使用和方便移植的中斷程序,一般都盡量使用DOS功能調(diào)用。5.3.5

系統(tǒng)功能調(diào)用DOS系統(tǒng)為程序設(shè)計(jì)人員提供了許多功能調(diào)用,即功能子程序,供用戶調(diào)用。調(diào)用時使用中斷指令:

INTn

其中,n為中斷調(diào)用類型號,其范圍是10H~0FFH。INT指令的執(zhí)行過程為:

(1)保護(hù)現(xiàn)場

SP←SP-2,SS:SP←FLAGSSP←SP-2,SS:SP←INTn下一條指令的CSSP←SP-2,SS:SP←INTn下一條指令的IPIP←[0000:n×4],CS←[0000:n×4+2](2)查中斷矢量表,獲得中斷程序的入口地址,并執(zhí)行中斷服務(wù)程序中斷服務(wù)程序執(zhí)行完后,用中斷返回指令I(lǐng)RET,恢復(fù)被中斷程序的斷點(diǎn)地址和CPU狀態(tài),返回被中斷程序繼續(xù)執(zhí)行。此時若有出口參數(shù),應(yīng)將其放在指定的寄存器或存儲單元中,讓用戶可以取出使用。DOS系統(tǒng)功能調(diào)用通常是指對類型號是21H的軟中斷子功能的調(diào)用,INT21H中斷保護(hù)多個子程序,每個子程序

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論