![匯編語言課件_第1頁](http://file4.renrendoc.com/view12/M09/39/11/wKhkGWcQ4EqAD5_EAAPMlIcHBsA894.jpg)
![匯編語言課件_第2頁](http://file4.renrendoc.com/view12/M09/39/11/wKhkGWcQ4EqAD5_EAAPMlIcHBsA8942.jpg)
![匯編語言課件_第3頁](http://file4.renrendoc.com/view12/M09/39/11/wKhkGWcQ4EqAD5_EAAPMlIcHBsA8943.jpg)
![匯編語言課件_第4頁](http://file4.renrendoc.com/view12/M09/39/11/wKhkGWcQ4EqAD5_EAAPMlIcHBsA8944.jpg)
![匯編語言課件_第5頁](http://file4.renrendoc.com/view12/M09/39/11/wKhkGWcQ4EqAD5_EAAPMlIcHBsA8945.jpg)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第1章第2章第3章第4章第5章第6章第7章第8章第9章第10章
第二早
匯編語言程序設(shè)計
指令系統(tǒng)中的指令,在計算機內(nèi)存中,都是以二進制編碼的形式存儲的,這種編碼
稱為機器碼,或者稱為機器指令.在程序運行時,指令由內(nèi)存讀入CPU,然后譯碼,
執(zhí)行.只有內(nèi)存中的機器碼,計算機才能執(zhí)行.然而,.機器碼很難記憶,使用時極
易出錯,因此,直接利用機器碼編制程序是極其困難又枯燥乏味的工作.編程的程
序,晦澀難懂,即使編程者本人,,編程后不出數(shù)日,對自己的程序,也可能不解其
慧,需仔細琢磨才能恍然大悟.這時,若有詳細的程序注釋,那將會給你帶來極大
方便,免除再度疲勞之苦.
實際的需要激發(fā)人們?nèi)?chuàng)造一種符號一助記符,用他們?nèi)ゴ鏅C器碼來表示指令,
既有簡單明了的詞意,一目了然,又便于理解和記憶,于是,匯編語言應(yīng)運而生.
現(xiàn)在,我們可以用指令助記符和表示地址或數(shù)據(jù)等的各種符號,按照規(guī)定的格式,
來編制程序,這樣的程序,稱為匯編語言程序.這些表示指令,地址,數(shù)據(jù)等的符號
以及有關(guān)規(guī)定,是計算機進行:“思想”的工具,亦即計算機匯編語言.
匯編語言與具體的計算機類型有密切的關(guān)系,不同的中央處理單元,其指令系統(tǒng)
也各不相同,相應(yīng)的匯編語言也互不相同.與硬件關(guān)系密切的程序,或者實時性要
求很高的程序,往往采用匯編程序.
在編輯程序的支持下,匯編語言程序從鍵盤輸入,編輯形成匯編語言源程序.源程
序是用匯編語言的語句編寫的,在計算機內(nèi)部,源程序的各條語句是以ascii碼
表示的,存在磁盤上,又稱為源文件。它區(qū)別與機器指令之處是不能被計算機執(zhí)行,
但它可以用來顯示和打印,作為檢查和保存的檔案.
匯編語言源程序經(jīng)過匯編程序的語法檢查和翻譯,形成二進制代碼表示的目的碼
文件.如果源程序中有語法錯誤,匯編程序會指出錯誤的類型和出錯所在的語句,
以便用戶重新進行編輯修改,再形成新的源程序.源文件和有其生成的目的碼文
件可以是一個或者是兒個.
目的碼文件并不能直接上機運行,必須經(jīng)過連接程序把它和庫文件連接在一起,
形成可執(zhí)行文件.這個可執(zhí)行文件有操作系統(tǒng)裝入計算機內(nèi)存,才能運行.
本章介紹匯編語言的語法規(guī)則,它是匯編語言的“法律”,編程時必須遵循,同時
也介紹匯編語言程序設(shè)計方法,以共參考.
3.1宏匯編基本語法
ibmpc微機中,有兩個匯編程序,一個是小匯編程序asm,另一個是宏匯編程序
masm,宏匯編程序功能比較強,并且支持宏匯編和有關(guān)的函數(shù)及偽指令,自然它需
要的存儲容量,比小匯編程序所需要的要稍微大一些.
3.1.1匯編語言程序舉例
我們通過一個例子介紹匯編語言的格式.這個例子的功能是把block中的正數(shù),
負數(shù)分別送到兩個緩沖區(qū)中去.程序如下:
datasegment;定義數(shù)據(jù)段
blockdb43h,Oabh;定義block變量及其數(shù)據(jù)初值
pdatadb20dup(?);定義存放正數(shù)的緩沖區(qū)
npatadb20dup(?);定義存放負數(shù)的緩沖區(qū)
dataends;數(shù)據(jù)段定義結(jié)束
codesegment;定義碼段
assumecs:code,ds:data;確定cs,ds和對應(yīng)段的關(guān)系
explprofar;定義過程
start:pushds;保存原ds
movax,0
pushas;ax;保存在堆棧
movax,data
movds,ax;數(shù)據(jù)段段址送ds,es
moves,ax
leasi,block;分別置偏移地址
leadi,pdata
leabx,ndata
cld
movex,pdata-block;數(shù)據(jù)個數(shù)送ex
goon:lodsb;數(shù)據(jù)送al
testal,80h
jnzminus;判是負數(shù),則轉(zhuǎn)minus
stosb;判是正數(shù),送去存入緩沖器
jmpagain
minus:xchgbx,di;交換,使di中為負數(shù)緩沖器便址
stosb;存負數(shù)
xchgbx,di;恢復(fù)原便址寄存器
again:loopgoon;循環(huán)次數(shù)未完,則轉(zhuǎn)goon
ret;返回dos
explendp;過程定義結(jié)束
codeends;碼段定義結(jié)束
endstart;匯編結(jié)束,斷定入口地址
從這個例子,不難發(fā)現(xiàn)匯編語言程序通常由數(shù)據(jù)段,碼段組成.數(shù)據(jù)段存放數(shù)據(jù),
碼段存放程序指令,實現(xiàn)相應(yīng)的功能.程序結(jié)束處,必須是規(guī)定程序執(zhí)行的起始地
址,也稱為入口地址.本程序開始執(zhí)行的地址是start.
程序語句行由四個部分組成,即標(biāo)號(或名字),操作碼,操作數(shù)和注釋.語句左邊
第?列起為標(biāo)號區(qū),句末分號后的為注釋區(qū),中間的部分為操作數(shù)區(qū).按照這種格
式書寫并輸入計算機,既是程序的要求,也使人閱讀時清清楚楚,賞心悅目.
3.1.2匯編語言程序結(jié)構(gòu)
匯編語言源程序通常由一個或兒個程序模塊組成,每個模塊包括數(shù)據(jù)段,堆棧段
和若干個代碼段.有時程序中可以不設(shè)堆棧段,而利用系統(tǒng)中已設(shè)定的堆棧段.代
碼段中有若干個過程,過程又稱子程序。過程中的語句分為兩類,兩類是指示性
語句,另一類是指示性語句.指示性語句是計算機能執(zhí)行的指令,而指示性語句,
計算機并不能執(zhí)行。匯編時,依據(jù)指示性語句的規(guī)定,匯編程序?qū)υ闯绦蜻M行相
應(yīng)的處理操作,進行諸如定義數(shù)據(jù)、分配存儲區(qū)、指示程序開始和結(jié)束等服務(wù)性
工作,以減輕編程員的負擔(dān)。指示性語句又成偽指令。
這里,用等式表示程序和過程的結(jié)果內(nèi)容:
程序={塊[數(shù)據(jù)段,堆棧段,代碼段(過程1,過程2,……)],快……}
過程={指示性語句,指令性語句}
指示性語句的格式如下:
[名字][偽指令][操作數(shù)][;注釋]
例如:
SUMPROCFAR;定義一個過程
SUMENDP;過程定義結(jié)束
指令性語句的格式為:
[標(biāo)號:][前綴][指令助記符][操作數(shù)][;注釋]
例如:
LP1:MOVBX,OFFSETDAREA;DAREA的地址送BX
語句中名字和符號,又稱為符標(biāo)識符,是程序員自己確定的,它不允許與指令助
記符或偽指令同名,也不允許有數(shù)字打頭,字符個數(shù)不得超過31個。
3.1.3數(shù)據(jù)項與表達式
操作數(shù)是指令和偽指令中很重要的一部分內(nèi)容,它可以用寄存器、存儲器單元或
數(shù)據(jù)項來表示。其中,數(shù)據(jù)項是最靈活多變的,它有三種形式:常量、標(biāo)號、變
量。常量、變量和標(biāo)號以及他們的表達式都可以作為操作數(shù)使用。下面分別介紹。
1常量
常量包括數(shù)字常量和字符常量兩種。
(1)數(shù)字常量
二進制常量——以字母為結(jié)尾的數(shù)為二進制數(shù)。例如,10111010。
十進制常量——以字母結(jié)尾或沒有字母結(jié)尾的數(shù)為十進制數(shù)。例如8914,2376
十六進制常量——以字母結(jié)尾的數(shù)為十六進制數(shù)。例如1在匯編程序中,凡是以
字母開始的十六進制數(shù),必須在前面加上數(shù)字0,以避免和表示符相混淆。
(2)字符串常量
以單引號內(nèi)一個或多個ASCH字符構(gòu)成字符串常量。匯編程序把他們翻譯成對應(yīng)
的ASCH碼值,一個字符對應(yīng)一個字節(jié)。例如,字符串常量,AB,和'C,在匯
編時分別被翻譯成4142H和43Ho
2.標(biāo)號
標(biāo)號是存放某條指令的存儲單元的符號地址,通常他用作條件轉(zhuǎn)移,無條件轉(zhuǎn)移
指令或調(diào)用指令的目標(biāo)操作數(shù)。
標(biāo)號是由標(biāo)識符即標(biāo)號后面跟一個冒號來定義的。例如:
START:MOVAX,DATA
LP1:MOVCX,COUNT
這兩條語句分別定義了兩個標(biāo)號START和LP1,他們可以供轉(zhuǎn)移指令,循環(huán)指令
或調(diào)用指令當(dāng)作目標(biāo)操作數(shù)來使用。
標(biāo)號作為存儲單元的符號地址,他具有3種屬性:段值,偏移量和類型。標(biāo)號的
段值,偏移量屬性分別指它的段地址和偏移地址,而標(biāo)號的類型分NEAR和FAR
兩種。
NEAR類型的標(biāo)號是指標(biāo)號所在的語句和調(diào)用指令或轉(zhuǎn)移指令在同一個碼段中,
執(zhí)行調(diào)用指令或轉(zhuǎn)移指令時,只需要把標(biāo)號的偏移地址送給IP,就可以實現(xiàn)調(diào)
用或轉(zhuǎn)移,并不需要改變碼段段址。
而FAR和NEAR類型不同,F(xiàn)AR類型標(biāo)號所在語句與其調(diào)用指令或轉(zhuǎn)移指令不
在用一碼段中,執(zhí)行調(diào)用指令或轉(zhuǎn)移指令時,不僅需要改變偏址IP的值,而且
需要改變段值CS的值。這是段間的調(diào)用或轉(zhuǎn)移。
3.變量
變量是內(nèi)存中的數(shù)據(jù)區(qū),由若干個存儲單元構(gòu)成,內(nèi)存中的內(nèi)容是可以修改的,
因此,變量的值也是可以哦改變的。變量在程序中,作為存儲器操作數(shù)來使用。
變量具有3中屬性:
(1)段值(SEGMENT)——變量定義所在段的段地址。為了確保匯編程序能找
到該變量,應(yīng)在偽指令(ASSUME)中加以說明,把其段值放在一個短寄存器中,
如CS,DS,ES或SS。
(2)偏移量(OFFSET)一—變量的地址和變量所在段的起始地址之間的偏移量。
(3)類型(TYPE)——變量的類型定義了該變量存儲區(qū)內(nèi)每個數(shù)據(jù)所占內(nèi)存單
元的字節(jié)數(shù),如字節(jié),字,雙字類型變量分別站用內(nèi)存1,2,4個字節(jié)單元。
變量定義的格式如下:
[變量名],[數(shù)據(jù)定義偽操作],[表達式]
變量名有字母打頭,最多允許31個字符,定義以后,凡是用到這個變量名時,
必須注意其三個屬性。數(shù)據(jù)定義偽操作將該變量名定義成某種類型的變量(數(shù)據(jù)
定義偽操作在以后敘述)。而表達式則確定了變量的初值和這個變量數(shù)據(jù)區(qū)的大
小,它允許采用數(shù)值表達式或地址表達式。
變量使用時,要注意以下幾點:
(1)變量類型與指令要求的操作數(shù)類型相符。例如,MOVAL,VARI指令中,
要求VARI應(yīng)該是字節(jié)類型的,才與AL的類型匹配。而指令MOVBX,VAR2則要
求VAR2應(yīng)該定義成字類型的變量。
(2)變量的編址。變量定義以后,變量名僅僅對應(yīng)這個數(shù)據(jù)區(qū)的首地址。若這
個數(shù)據(jù)區(qū)中有若干個數(shù)據(jù)項,在對其后面的數(shù)據(jù)項進行操作時,其地址需要改變。
例如,欲求變量XY數(shù)據(jù)區(qū)中20個字的和,在加下一個數(shù)據(jù)項時,地址應(yīng)該進行
修改,以指向那個數(shù)據(jù)項。具體程序段如下:
XYDW20DUP(?)
MOVAX,XY+38;送最后一個字給AX
MOVBX,38
LP1:SUBBX,2;偏址修改
ADDAX,XY[BX];求和
CUPBX,0;判是否是第一個數(shù)字
JNELP1;不是,則幾需求和
(3)變量的斷址。指令中的操作數(shù)的斷址往往不直接表示出來,而是隱含的,
或者稱為默認的或缺省的。變量使用時,其段屬性應(yīng)與所在指令的缺省段寄存器
相符。如若不符,應(yīng)該把段地址直接表示出來,這種表示方法,稱為跨段前綴。
跨段前綴可以用段寄存器或段名來表示。例如:
MOVAX,ES:[BX]
MOVAX,DATA:[DI]
4表達式
匯編程序允許使用表達式。然而,表達式并不是指令,它本身不能執(zhí)行。程序被
匯編時,匯編程序?qū)Τ绦蛑械谋磉_式進行相應(yīng)的運算,其運算結(jié)果是一個值。因
此,在程序被執(zhí)行時,表達式本身已經(jīng)是一個有確定值的操作數(shù)。
變達式中的運算有三類運算符一一算術(shù)運算符、邏輯運算符和關(guān)系運算符來表
/J、.O
(1)算術(shù)運算符
有+,*,/,MOD五種算術(shù)運算符,前面4種是最常見到的加、減、乘、除、
四則運算符,而MOD是表示求兩個數(shù)相除以后的余數(shù)。例如,23M0D7其結(jié)果是
2,即23除以7,其余數(shù)是2。
算術(shù)運算符用于數(shù)字表達式,其結(jié)果仍是數(shù)字。
算術(shù)運算符也可以用于地址表達式,但其應(yīng)用范圍受到一定的限制,那就是地址
表達式的運算必須有明確的物理意義,其運算結(jié)果才有效,否則該地址表達式是
錯誤的。
通常,地址表達式中使用加或者減運算。地址加或者減一個數(shù)字量,表示對原地
址偏移該數(shù)字的若干個單元的地址。例如,VAR+2表示變量VAR的地址加上2
得到的和作為新的存儲單元的地址。同一段中兩個存儲單元地址之差,表示他們
之間的地址偏移量,或者有時表示這兩個存儲單元之間有多少個字節(jié)。而不同段
址的兩個偏移地址的加或者減是沒有物理意義的,兩個地址相乘或相除同樣也是
沒有物理意義的。例如,若要把字數(shù)祖阿惹第九個字傳到AX寄存器,用指令可
以這樣表示:
MOVAX,VAR+(9T)*2
其中,VAR是該數(shù)組的首地址,(9T)*2是第9個字的地址與首地址的偏移量。
(2)邏輯運算符
有AND,OR,NOT和XOR四種邏輯運算符,邏輯運算是按位操作的,邏輯運算符
只能用于數(shù)字表達式,不能用于存儲器地址表達式。例如:
MOVAL,OADHANDOCCH
匯編時,計算上式中右邊邏輯表達式,得到結(jié)果為8cH,這樣就轉(zhuǎn)化為指令
MOVAL,8CH
表達式VAROR80H是無效的,因為邏輯運算符不能用于地址表達式。
那么,指令OUTPORTANDFEH,AL是否有效呢?答案是肯定的,有效。因為PORT
是1個字節(jié)的數(shù)字,而不是一個變量,盡管它名義上是作為外設(shè)口的地址,實
際上匯編程序認為它是一個數(shù)字,PORT是?個數(shù)字表達式,因此允許使用邏輯
運算符。該指令在匯編時,若PORT是偶數(shù),則表達式結(jié)果與原端口號相同,若
PORT是奇數(shù)時,該指令的輸出端口為一偶數(shù),比PORT端口號小1。
這里需要提醒的是這些邏輯運算符是用于數(shù)字表達式的運算符,并不是邏輯運算
指令的操作碼。前者是匯編程序在進行匯編時處理的,而后者是在程序運行時執(zhí)
行的。
(3)關(guān)系運算符
有EQ,NE,LT,GT,LE,GE六種關(guān)系運算符。這些關(guān)系運算符分別表示兩個操
作數(shù)是否相等,不等,小于,大于,小于等于和大于等于。關(guān)系運算的兩個操作
數(shù)必須都是數(shù)字或者都是同一段內(nèi)的存儲器地址。關(guān)系運算的結(jié)果是一個邏輯
值,結(jié)果為真,邏輯值是OFFFFH;結(jié)果為假,值為0。例如:
MOVAX,VARIGTVAR2
如果VARI地址大于VAR2,則匯編結(jié)果應(yīng)該是:
MOVAX,OFFFFH
否則,匯編結(jié)果就成為:
MOVAX,0000H
數(shù)字表達式比較容易理解,而地址表達式比較復(fù)雜。
地址表達式由變量,標(biāo)號,常量,基址,變址寄存器以及相關(guān)的運算符組成,它
表示了存儲器的地址。地址表達式有三種屬性,即段值,偏移量,類型。地址表
達式的段值,偏移量即是其段地址和偏移地址。而類型則有字節(jié),字和雙字類型,
以及近(NEAR)和遠(FAR)類型兩種,前者和數(shù)據(jù)的存儲單元相對應(yīng),后者與
程序轉(zhuǎn)移或調(diào)用的目標(biāo)地址相對應(yīng)。
和地址表達式有關(guān)的運算符,除了前面所提及的,還有下面兩種操作符。
(1)類型操作符一一PTR程序中對變量或標(biāo)號定義后,變量或標(biāo)號的屬性便確
定了。也就是有它的段址,偏址和類型。但在實際使用時,可能會出現(xiàn)與原先定
義的類型不匹配的情況,需要臨時加以調(diào)整。PTR操作符給地址表達式臨時賦予
一個新的類型,而地址表達式的斷值,偏移量屬性不便。其操作的格式如下:
類型地址表達式
其中的類型可以是或
例如,給已定義為字:
varidw?
那么,只能在字操作令中使用vari這個變量,如movax,varl時合法的。但是,
要把varl當(dāng)作字操作數(shù)來使用,便是非法的,指令
movvari,al
會出現(xiàn)類型不配的錯誤,而指令
movbyteptrvarl,al
則合法的。操作符ptr產(chǎn)生了一個新的地址操作數(shù),該操作數(shù)的段地址和偏移地
址與varl相同,而類型為字節(jié)型,不是原先定義的字類型。
若標(biāo)號next原來定義是near類型,現(xiàn)在另一個段中的程序要轉(zhuǎn)移到此next處,
那么采用指令
jmpfarptrnext
來實現(xiàn)段間的轉(zhuǎn)移。
(2)樹枝返回操作符——segoffset有時,并不希望對變量的內(nèi)容進行處理,
而需要這個變量的地址以便量進行操作;有時,并不希望轉(zhuǎn)移到某個標(biāo)號定義
的目標(biāo)地址去,而是需要對這個標(biāo)號的地址進行處理。在這兩種情況下,需要利
用seg和offset這兩個數(shù)值返回操作符,他的操作格式如下:
seg變量或標(biāo)號
offseg變量或標(biāo)號
seg操作符返回變量或者標(biāo)號的段址。而offseg操作符返回變量或者標(biāo)號的偏
移量。
例如:
movaxmsegvarname
movbx,offsegvarname
分別得到varname段址和對短起始地址的偏移量,傳送給ax和bx寄存器。
32指示性語句
指示性語句.偽操作語句。偽操作不是計算機指令系統(tǒng)的一部分,而是匯編程序
提供源程序的服務(wù)工具,用以完成會變得輔助性工作,諸如變量定義,符號賦值,
程序守為標(biāo)志等。Ibm宏匯編提供以下兒類操作語句:變量定義語句:符號賦值
語句;斷定義語句;過程定義語句;??於x語句。
下面對這兒類為操作的常用部分加以敘述。書中沒有涉及的偽操作,讀者需要是
可以查閱手冊。
3.2.1變量定語句
變量定義語句為變量分配若干個初值。這一類操作的格式為:
[變量名]助記符操桌數(shù)。?!僮罃?shù)[;注釋]
其中變量子段名用符號地址表示,分配的春儲單元的第一個字節(jié)的偏移地址是這
個變量名的值。這個變量名字段也可以沒有,表示只分配若干個存儲單元。
注釋子段用來對該偽朝作做一些說明,如它的功能等。
超作數(shù)子段可以有若個個操捉數(shù),偽操作把這些數(shù)據(jù)存入指定的存儲單元。這里
操作數(shù)可以是指定的數(shù)值表達式、ASC字符穿、地址表達式。助記符字段是定義
變量的偽操作,常用的有DB,DW,DD等兒種。
DB偽操作用來定義字節(jié)形變量,其中的每個操作數(shù)都占有一個字節(jié)存儲單元,
每個操作數(shù)的值不操過255。
DW偽操作用來定義字形變量,其中的每個操作數(shù)都占有兩個字節(jié),字的低位字
節(jié)在第一個字節(jié)地址單元中,字的低位字節(jié)在第二個字節(jié)地址單元中,簡單的說,
就是低位在前、高位在后、或低位低地址、高位高地址。
DD偽操作用來定義雙字型變量,其中的每個操作數(shù)都占有兩個字,雙字的最低
位字節(jié)在第一個字節(jié)地址單元中,次低位字節(jié)在第二個字節(jié)地址單元中,次高位
字節(jié)在第三個字節(jié)地址單元中,高位字節(jié)在第四個字節(jié)地址單元中。
例操作數(shù)是常數(shù)或者表達式。
BYTE_VARDB12,4,12H
WORD_VARDW100H,-2,10*6
DW_VARDDOFEFDH
匯編程序在匯編時,根據(jù)表達式可以求得一個常數(shù),把數(shù)據(jù)結(jié)果存入存儲器,如圖
3-1.
例操作數(shù)可以是字符串,如:
STRINGDB'OK!'
CHARDB'AB'
WARDDW'AB'
匯編后,存儲器的存儲情況如圖3-2所示.
例操作數(shù)字段用符號?來表示,即保留存儲空間,不存入起始數(shù)值.操作數(shù)字段
也可以用復(fù)制操作符DUP復(fù)制某些數(shù)據(jù),如:
ARRAY1DB4DUP(?)
ARRAY2DB10DUP(0,1)
DUP前面的數(shù)據(jù)指定括號中的操作數(shù)的重復(fù)次數(shù),它可以是一個表達式.匯編后,
存儲器的存儲情況如圖3-3.
3.2.2符號賦值語句
程序中,有時多次出現(xiàn)同一個表達式,為了方便起見,用賦值偽操作給表達式賦予
一個符號名,以后,凡用到該表達式的地方都可以用這個符號名來表示,這樣,意
義清楚,修改容易.格式如下:
符號名EQU表達式
其中表達式可以是任何有效的操作數(shù),可以是任何結(jié)果為常數(shù)的表達式,也可以
是助組記符.例如:
COUNTEQU256
BEQU[BP+8]
P8EQUDS:[BP+8]
LPNEQULP1+12H;給^^賦地址表達式
SSBEQUSTOSB
EQU語句的表達式中,如果有變量或符號出現(xiàn),則在該語句前后必須給出它們的
定義,表達式才有效,否則匯編程序?qū)⑻崾境鲥e.例中的第四個語句的LP1應(yīng)該在
次句前加以定義.
符號用EQU語句賦值后,不能重新賦值.除非用PURGE語句解除這些賦值關(guān)系,符
號才能賦新的值.PURGE語句的格式為:
PURGE符號1,符號2,…,符號n,
而另一個與EQU語句功能類似的語句,即=偽操作.=偽操作允許給符號賦一個常
量,或者結(jié)果是常數(shù)的表達式,并且允許對符號重新賦值.例如:
EMP=16
EMP=17
EMP=EMP+1
3.2.3段定義語句
前面我們已經(jīng)講過,8086和8088的存儲器的物理地址由段地址和偏移地址組合
而成.程序運行時,程序的指令和變量都存在某個段內(nèi).因此,匯編程序按段來組
織程序和數(shù)據(jù),變量.與段有關(guān)的主要偽操作有SEGMENT;ENDS;ASSUME;ORG.
段定義的格式如下:
segnameSEGMENT
segnameENDS
每個段必須有一個名字,每個段定義由SEGMENT開始,到ENDS結(jié)束,兩者少一不可,
并且其語句中的名字必須相同,否則,匯編程序無法辨認.省下的部分,數(shù)據(jù)段,附
加段和堆棧段來說,一般是變量,符號定義等偽操作,而對于代碼段則是指令及有
關(guān)偽操作.定義段之后,還需要用ASSUME偽操作語句,以確定段和段寄存器的關(guān)
系.其格式為:
ASSUMEseg-reg;segname[,,,,]
其中段寄存器名必須是CS,DS,ES,SS中的一個,而段名是由SEGMENT和ENDS定
義的段中的段名.欲取消前面的ASSUME語句確定的段與段寄存器的關(guān)系,可采
用ASSUMENOTHING語句.例如:
datalSEGMENT
XIDB?
X2DW?
X3DD?
datalENDS
extralSEGMENT
ylDB?
y2DW?
y3DD?
extralENDS
stacklSEGMENT
DW100HDUP(?)
TopEQUTHISWORD;THIS是個運算符,它建立一個新的存儲器地址操作數(shù),
stacklENDS;其地址為匯編時的當(dāng)時值,類型由THIS后的項指定.
CODESEGMENT
ASSUMECS:CODE,DS:datal,ES:extral,SS:stackl
BEGIN:MOVAX,datal
MOVDS,AX
MOVAX,extral
MOVES,AX
MOVAX,syackl
MOVSS,AX
CODEENDS
ENDBEGIN
ASSUME語句確定了短與段寄存器的對應(yīng)關(guān)系,供匯編時使用,而段地址裝入段寄
存器,即段寄存器的賦值,還需要代碼中的MOV指令來完成.不過,碼段寄存器例
外,它是在程序初始化時,由系統(tǒng)程序完成的,不需要也不允許用戶給CS賦值.用
戶程序模塊可以存放在一個或幾個碼段中,根據(jù)需要定.
SEGMENT偽操作還可以增加一些說明,格式如下:
SegnameSEGMENT[align-type][combine-type][,class']
這三種類型說明分別敘述如下:
(1)定位類型(align-type)
PARA該段的起始地址從段的邊界開始,也就是段地址的最低位必定為0(十六進
制數(shù)表示).通常隱含.
BYTE該段可以從任何有效地址開始.
WORD該段的起始地址必須是偶數(shù),即從字的邊界開始.
PAGE該段的起始地址從頁邊界開始,即段地址最低兩個十六進制數(shù)位為0(一頁
為256字節(jié)).
(2)組合類型(combine-type)
PUBLIC規(guī)定連接時該段要和其他具有相同的段名的段連接在一起,形成一個段,
連接的次序在調(diào)用LINK程序時由用戶指定.
COMMON規(guī)定連接時該段和其他同名段具有相同的起始地址.因而產(chǎn)生覆
蓋.COMMON的連接長度是同名段中的最大長度.
ATexpression規(guī)定表達式計算結(jié)果的16位二進制值為段的起始地址.但不能用
于指定代碼段,而用于固定地址的數(shù)據(jù)段,如ROM中的數(shù)據(jù)區(qū),或存儲區(qū)中的向量
表.
STACK規(guī)定該段在運行時是堆棧段的一部分.
MEMORY規(guī)定該段定在所有其他連接段的后面.
(3)類別('class')
它是一個名字,用于連接時組成同名段組.
偽操作指令ORG語句規(guī)定了程序段或數(shù)據(jù)塊在該段內(nèi)的起始地址,其格式為
ORGexpression
其中表達式expression的值即為段內(nèi)的起始地址或偏移地址,從此地址起連續(xù)
存放程序或數(shù)據(jù).
3.2.4過程定義語句
一個過程具有某一種功能,形成獨立的程序塊,它是匯編程序的基本單位.
過程定義的格式如下:
procedure-namePROC
RET
procedure-nameENDP
過程定義的偽操作PROC和ENDP必須成對出現(xiàn).在過程的首尾處,必須有過程名起
頭.過程結(jié)束處往往有RET語句,以返回調(diào)用它的程序處.有時RET語句也可以出
現(xiàn)在過程中間.過程至少有一個入口和出口,以供進入和脫離該程序.
按上面定義,只能在該程序的同一碼段中被調(diào)用.過程應(yīng)賦予FAR的屬性,格式如
下:
procedure-namePROCFAR
procedure-nameENDP
調(diào)用過程和從過程返回有兩種情況:段內(nèi)的和短間的.
段內(nèi)的調(diào)用和返回指令執(zhí)行時,推入堆棧和退出堆棧的僅僅是應(yīng)該返回處的段內(nèi)
的地址偏移量.
段間的調(diào)用和返回指令執(zhí)行時,推入堆棧和退出堆棧的僅僅是應(yīng)該返回處的段地
址和段內(nèi)偏移量.
在定義時,可以用NEAR屬性顯式地表示:
procedure-namePROCNEAR
procedure-nameENDP
3.2.5程序模塊定義
每一個程序模塊的開始,往往要用NAME或TITLE為其取一個名字,模塊結(jié)束,則需
要用END偽操作來告知匯編程序,在遇到END語句時結(jié)束匯編.
NAME的格式為:
NAMEmodule-name
匯編程序把NAME后面的module-name作為模塊的名字,這個名字不允許使用保留
字,可以使用標(biāo)識符.
TIYLE的偽操作,格式是:
TITLEtext
它為清單的每一頁指定打印的標(biāo)題.text
中最多允許60個字符.若無NAME偽操作,則把text
中的前6個字符作為模塊名.若既無NAME又無TITLE偽操作,則就吧源文件名作
為模塊名.
知NAME和TITLE偽操作并不是必須的.
但每個模塊的結(jié)束,必須要有END偽操作,格式為:
END[label]
其中,可選的標(biāo)號指示程序開始執(zhí)行的起始地址。如果若干個個程序??煜嗦?lián)接,
那么只有住程序??煨枰褂脦霕?biāo)號的語句,而其他程序模塊是被調(diào)用的,
不能使用帶入標(biāo)號的語句,只需要。
下面是一個兩個數(shù)差的絕對值的程序。
Titledifference
Datasegment
Dumldw250h
Dum2dwla9h
Resultdw?
Dataends
Codesegment
Assumecs:code,ds:data
Mainprocfar
Start:movax,data
Movds,ax
Movax,numl
Subax,num2
Jnbstore
Negax
Store:movresult,ax
Movah,4ch
Int21h
Mainendp
Codeends
Ends
Endstart
這個有一個程序??旖M成,他從為操作開始,為操作結(jié)束。語句制定了該程
序的入口地址,此入口地址在程序在該程序中正好是第一條執(zhí)行指令的地址,這
個程序丁宜樂了一個數(shù)據(jù)段和一個媽段,碼段中紙包裹一個過程,過程結(jié)束時,
通過調(diào)用的的功能,返回,程序結(jié)束運行。
3.3匯編語言程序設(shè)計程序
第二章介紹了指令系統(tǒng),結(jié)合指令也給出了一些程序段例子,本章的第一二節(jié)由
介紹了紅會變得基本語法和偽指令。有了這些基礎(chǔ)知識,就不難進行匯編語言的
程序設(shè)計。
從下一節(jié)起,介紹匯編語言程序設(shè)計的主要方法。這里次先介紹與匯編語言程序
有關(guān)的問題,以便在程序設(shè)計之前,引起大家的注意,少哦組一些彎路。
3.3.1程序的質(zhì)量標(biāo)準
再編程序時,首先要有一個質(zhì)量觀念,要編制質(zhì)量高的程序,而不僅僅是完成任
務(wù)。在進行學(xué)習(xí)時,要逐步養(yǎng)成良好的編程習(xí)慣。如同寫文章,撰寫的作品千只
百態(tài)一樣,用計算機敘述某個問題,也即編程,同樣千差萬別。衡量程序的質(zhì)量,
通稱有四個標(biāo)準:
(1)程序正確完整;
(2)程序易讀性;
(3)程序的執(zhí)行時間;
(4)程序所占內(nèi)存大小及程序行數(shù)。
其中,第一條是主要的,最基本的。往往有些程序基本功能是正確的,但隱藏著
一些問題,或者在某些情況下執(zhí)行是正確的,而在另外的情況下程序運行的結(jié)果
是不對的。程序的一讀性對軟件的維護和軟件設(shè)計的合作是大有裨益的,因此已
開始就養(yǎng)成良好的編程習(xí)慣,編程思路要清楚,畫一個流程圖,在程序前部隊變
量和算法加以說明,在程序中對有關(guān)語句加上注釋。程序的執(zhí)行時間對于實時處
理的問題環(huán)重要的。程序所占內(nèi)存大小對于復(fù)雜的大程序來說,也不能等閑視之,
而考慮到軟件的開發(fā)成本,程序的語句則是一個很重要的因素。
3.3.2
(1)把實際問題抽象,提煉成數(shù)學(xué)模型。
(2)確定解決該數(shù)學(xué)模型的算法.
(3)程序模塊分析。在分析復(fù)雜的實際問題時,往往需要把它分成若干功能塊,畫
出層次圖,確定各塊間的通信。對于簡單的問題,僅僅一個模塊足以完成其任務(wù),
就無須模塊分析.
⑷畫出模塊程序圖.
⑸分配內(nèi)存工作單元和寄存器.
(6)根據(jù)流程圖編制程序.
(7)上機調(diào)試,進行修改,最后檢測通過.
編制過程的第一步,數(shù)學(xué)抽象,是很重要的一環(huán),它關(guān)系到全局,不可輕視.實際
工作中,因為抽象不準確,以致返工的是屢見不鮮.確定算法亦是關(guān)鍵的一步,它
與程序質(zhì)量的高低密不可分,它決定了程序的復(fù)雜程度和執(zhí)行時間的長短.其后
的模塊分析,編制流程圖和程序,也往往要通過調(diào)試進行相應(yīng)的修正.
3.3.3程序流程圖
程序流程圖是一種算法表達工具,它根據(jù)算法,將結(jié)局問題的思路和方法用字符
和圖形表示出來,確定程序的結(jié)構(gòu)和程序的流向.
對于處學(xué)者,程序流程圖是比不可少的工具.對于熟練的編程者,在編制復(fù)雜的程
序時,仍然少不了流程圖的支持。它便于編制程序,便于調(diào)試程序,有利于減少程
序的錯誤,提高程序效率.
本書的流程圖,采用國際標(biāo)準,它與我國國標(biāo)也是基本一致的。所用主要的符號
如下:
(1)矩形框表示各種處理的功能,框中用簡明的語言表明所完成的處理功能.例
如執(zhí)行一個加法操作.這種處理有一個入口和一個出口,有箭頭表示.
(2)菱形框表示判斷,框內(nèi)表明判斷的條件.它有一個入口,但可以有若干個出
口,分別用箭頭表示。在各個出口處表明該出口的條件,例如條件滿足用y表示,
條件不滿足時用n表示.
(3)特定的方框表示特定處理,通常表示子程序,模塊??騼?nèi)表明程序名或模塊名,
框縱邊為雙數(shù),形如
(4)端點框六邊形表示程序流程的起點,扁圓形框表示程序的終點.
(5)流線帶箭頭的直線,表示程序的流向,它連接程序的各個流程圖,新的圖表
正向流線不帶箭頭,反向流線帶箭頭.
3.4數(shù)據(jù)輸入和輸出
程序通常要對數(shù)據(jù)進行處理,而后輸出結(jié)果.那么所需要的數(shù)據(jù)來自何處?他們可
能;來自:1程序的數(shù)據(jù)段,編程時預(yù)先設(shè)定;2磁盤,數(shù)據(jù)以數(shù)據(jù)文件的形式存在
盤上;3外設(shè),例如A/D轉(zhuǎn)換,把模擬信號轉(zhuǎn)成數(shù)字信號,送入計算機內(nèi)存;4鍵盤
輸入,這里,我們只討論鍵盤輸入的情況,其他的可以參考有關(guān)資料.
-一般高級語言的數(shù)據(jù)輸入輸出多有相應(yīng)的語句或函數(shù)倆處理,而匯編語言無法用
一條指令解決問題,他通過調(diào)用系統(tǒng)功能來完成這個任務(wù).調(diào)用系統(tǒng)功能猶如高
級語言中調(diào)用子程序,它需要先提供實際參數(shù)(又稱入口參數(shù))以及所調(diào)用的功
能號.調(diào)用結(jié)果返回結(jié)果,即可得到出口參數(shù).
3.4.1輸入字符串
從鍵盤上輸入字符串,可以得到一串字符的ASCII.如果是數(shù)字符,通過變換和組
合,就可以得到數(shù)據(jù).
輸入字符串,通過調(diào)用dos功能的Oah號功能來實現(xiàn).它需要一個字符緩沖區(qū),
以便存儲讀入的字符串。緩沖區(qū)的第一個字節(jié)保存字符去長度,它由用戶定義時
給出,不允許超過此限定數(shù).如果輸入的超過次數(shù),系統(tǒng)會拒絕接受,發(fā)出“嘟
嘟”聲,光標(biāo)也不再向右移動.
緩沖區(qū)的第二個字節(jié)是實際鍵入字符的個數(shù),鍵入完成后,系統(tǒng)程序會在那個單
元自動填入鍵入字符的個數(shù),它不是由用戶確定的,它也不包括最后結(jié)束字符串
輸入的回車字符,雖然此回車符還占用字符區(qū)的一個字節(jié).
緩沖區(qū)的的三個字節(jié)起,便是存放字符串的字符區(qū),它按字存放.例如.在數(shù)據(jù)區(qū)
定義了一個緩沖區(qū)BUFFER,字符區(qū)長度為20,可表示如下:
BUFFERDB20
REALENDB?
STRUNGDB20DUP(?)
調(diào)用A號功能的程序段如下:
LEADX,BUFFER;緩沖區(qū)首地址一WX
MOVAH,OAH;調(diào)用功能--aAH
INT21H;調(diào)用DOS的OAH功能
假如程序執(zhí)行時,鍵入字符
Thisisastring
那么,緩沖區(qū)BUFFER中各存儲單元的內(nèi)容如下所示:
其中第一個單元的14H是字符區(qū)長度,第二個單元的10H是實際鍵入字符的個數(shù),
字符區(qū)中是鍵入字符的ASCII串。ODH為回車符。
例從鍵盤上輸入一個字符串,并在串尾處加上字符串結(jié)束標(biāo)志。
;inputastringfromthekeyboard,
;thenwrite'$'attheendofthestring,asamark
?
DATASEGMENT
STRINGDB30,0,30DUP(?)
DATAENDS
CODESEGMENT
ASSUMECS:CODE,DS:DATA
KEYINPROCFAR
BEGINMOVAX,DATA
MOVDS,AX
MOVDS,AX
MOVDX,OFFSETSTRING
MOVAH,OAH
INT21H
MOVCL,STRING+1
XORCH,CH
ADDDX,2
ADDDX,CX
MOVBX,DX
MOVBYTEPTR[BX]
MOVAH,4CH
INT21H
KEYINENDP
CODEENDS
ENDBEGIN
3.4.2輸出字符串
內(nèi)存中的字符傳送到顯示器顯示,可以通過調(diào)用DOS功能的9號功能來實現(xiàn)。該
功能要求被現(xiàn)實的字符串必須是以ASCH碼。例如:
MESSAGEDB'THATISALL,GOODBYE!',13,10,f$'
但是其他的控制碼,不能出現(xiàn)在字符串中。顯示字符串的程序段為:
MOVAH,9
MOVDX,SEGMESSAGE
MOVDS,DX
LEADX,MESSAGE
INT21H
若要顯示數(shù)據(jù),必須先把他們轉(zhuǎn)換成ASCH碼,然后才能調(diào)用DOS的9號功能,
顯示他們。
3.5順序程序設(shè)計
順序城市最常見的,也是最基本的程序設(shè)計方法。這種程序在計算機內(nèi)村種執(zhí)行
時,按照先后次序,逐句順序執(zhí)行。他沒有分支也沒有循環(huán),因此也成為線性程
序。下面是一個例子。
例兩個64位無符號數(shù)相加的程序。
在8086/8088CPU中,數(shù)據(jù)是16位的,他有8位和16位運算指令,但是沒有32
位,64位這種16位以上的運算指令。要進行64位相加運算可以利用16位加法
指令分別相加4次來實現(xiàn)。具體程序如下:
DATASEMENT
NUM1DW1357H,2468H,90BDH,0ACEH
NUM2DW9753H,8264H,0B09DH,OFAEH
SUBNDW5DUP(?)
DATAENDS
CODESEGMENT
ASSUMECS:CODE,DS:DATA
ADD64PROCFAR
BEGIN:MOVAX,DATA
MOVDS,AX
LEABX,NUM1
MOVAX,[BX]
ADDAX,[BX+8]
MOV[BX+1OH],AX
INCBX
INCBX
MOVAX,[BX]
ADCAX,[BX+8]
MOV[BX+1OH],AX
INCBX
INCBX
MOVAX,[BX]
ADCAX,[BX+8]
MOV[BX+1OH],AX
INCBX
INCBX
MOVAX,[BX]
ADCAX,[BX+8]
MOV[BX+1OH],AX
MOVAX,0
ADCAX,0
MOVW[BX+12H],AX
MOVAH,4CH
INT21H;
ADD64ENDP
CODEENDS
ENDBEGIN
3.6分支程序設(shè)計
在程序中,除了最基本的順序結(jié)構(gòu)以外,通常還有各種分支,以滿足不同情況作
不同處理的需要。分支結(jié)構(gòu)有兩種形式,一種是引出兩個分支的,另一種是引出
多個分支的。前者類似于高級語言中的IF——THEN--ELSE語句,后者類似于
高級語言中的CASE語句,分若嘎呢請昂,進行不同的處理。程序在某種條件下
運行時,執(zhí)行其中一個分支。分支結(jié)構(gòu)如圖3—4所示。上述兩種結(jié)構(gòu)分別舉例
如下:
例從鍵盤上輸入兩個整數(shù),并求其和。
通過調(diào)用DOS功能,從鍵盤上輸入整數(shù)該數(shù)是以ASCII碼的形式存在內(nèi)存中的。
因此,需要把它轉(zhuǎn)化成二進制數(shù),在進行加法運算。如果計算機以一個字來表示
一個整數(shù)的話,整數(shù)的范圍應(yīng)在-32768于32767之間程序流程如圖3-5和-6所
/J、.O
DATASEGMENT
STR1DB7,?7DUP(?)
STR2DB7,?7DUP(?)
NUMDW?,?
BUFFERDW0
OVERDB'OVERFLOW!',13,10,'$
DATAENDS
CODESEGMENT
ASSUMECS:CODE,DS:DATA
MAINPROCFAR
START:MOVAX,DATA
MOVDS,AX
MOVAH,OAH
LEAAX,STR1
INT21H
MOVAH,OAH
LEADXSTR2
INT21H
LEABX,STR1
LEADI,NUM
CALLCHANGE
LEABX,STR2
LEADI,NUM+2
CALLCHANGE
MOVAX,NUM
ADDAX,NUM+2
MOVBUFFER,AX
JNONEXT
LEADX,OVER
MOVAH,9
INT21H
NEXT:MOVAH,4CH
INT21H
MAINENDP
CHANGEPROC
MOVCL,[BX+1]
MOVCX,[BX+2]
MOVCH,AL
CMPAL/-<
JNZNEXT1
DECCL
INCBX
NEXT1:ADDBX,2
MOVAX,0
LP1:DECCL
JZNEXT2
MOVDH,0
MOVDL,[BX]
ANDDL,OFH
ADDAX,DX
MOVDX,.AX
ADDAX,AX
ADDAX,AX
ADDAX,DX
INCBX
JMPSHORTLP1
NEXT2:MOVDL,[BX]
ANDDL,OFH
MOVDH,0
ADDAX,DX
CMPCH,'-'
JNZNEXT3
NEGAX
NEXT3:MOV[DI],AX
RET
CHANGEENDP
CODEENDS
ENDSTART
例根據(jù)AL寄存器中的內(nèi)容,把程序轉(zhuǎn)移到不同的程序分支中去。
若AL中的內(nèi)容是1,則轉(zhuǎn)到ROUTINE1去執(zhí)行,若AL中的內(nèi)容是2,則轉(zhuǎn)到
R0UTINE2去執(zhí)行,。。。。。。。。這種設(shè)計發(fā)方法又稱為跳轉(zhuǎn)表法,在程序
設(shè)計中常見到,很有用。例如,以惡程序分成若干個功能塊,每個功能塊實現(xiàn)不
同的功能可以當(dāng)作一個分支程序,根據(jù)不同的情況,執(zhí)行不同的分支,完成相應(yīng)
的功能,之后再返回主程序。
TABLESEGMENT
BRATABLEDWROUTINE1,ROUTINE2,ROUTINES,ROUTINE4,ROUTINES,R0UTINE6
TABLEENDS
CODESEGMENT
ASSUMECS:CODE,DS:TABLE
MAINPROCFAR
BEGINMOVAX,TABLE
MOVDS,AX
MOVCH,6
MOVCL,0
NEXT:INCCL
CMPCL,AL
JZ,GORUN
INCBX
INCBX
DECCH
JNZNEXT
JMPCOUTINE
GORUN:JMPWORDPTR[BX]
ROUTINE1:
R0UTINE2:
ROUTINES:
?????????????,
R0UTINE4:
ROUTINE5:
R0UTINE6:
????????????
ROUTINE:
MOVAH,4CH
INT21H
MAINENDP
CODEENDS
ENDBEGIN
這個程序中,分支標(biāo)的首地址在中BX中,BX作為分支表的指針,分支號在CL
中隨著分支號的增加,BX的內(nèi)容也發(fā)生變化,紙箱下一個分支的地址,因此當(dāng)
AL中的內(nèi)容與CL的內(nèi)容相等時,程序控制就轉(zhuǎn)到BX所致的那個分支去,從哪
兒在繼續(xù)執(zhí)行。各個分支執(zhí)行完后,轉(zhuǎn)向何處,可以有變成者根據(jù)需要來確定。
比如,讓此程序中的各個分支轉(zhuǎn)向CONTINUE,然后在結(jié)束。
3.7循環(huán)程序設(shè)計
循環(huán)程序也是程序的一種基本結(jié)構(gòu)。程序中,往往有的程序段需要重復(fù)執(zhí)行多次,
以實現(xiàn)某種功能,這樣,可以大大簡化程序設(shè)計。循環(huán)程序通常有以下三部分組
成:
1.循環(huán)初始狀態(tài)循環(huán)過程中的工作單元,在循環(huán)開始前,往往要給他們賦初
值,以保證循環(huán)能正常地進行工作。循環(huán)初始狀態(tài)包括循環(huán)工作部分初態(tài)和循環(huán)
部分初態(tài)。例如:設(shè)某些標(biāo)志,懾地址指針。某些寄存器清零,某些變量付出
制,循環(huán)控制寄存器賦初值等等。
2.2o循環(huán)體這是循環(huán)程序重復(fù)執(zhí)行的部分,是循環(huán)的主體。循環(huán)體包括循
環(huán)的工作部分和循環(huán)的修改部分。循環(huán)的工作部分是實現(xiàn)程序功能的程序段,它
是循環(huán)的主要部分。循環(huán)的修改部分是修改部分是修改參加循環(huán)的信息的程序
段,循環(huán)每次執(zhí)行時,有關(guān)信息能發(fā)生信息的相應(yīng)變化,確保循環(huán)程序正常循環(huán)。
3.循環(huán)控制循環(huán)能正常進行和結(jié)束,循環(huán)控制是關(guān)鍵。循環(huán)控制條件不合理,
循環(huán)就無法按正常的預(yù)定進行,甚至導(dǎo)致死循環(huán)。循環(huán)控制條件的選擇很靈活。
如果循環(huán)次數(shù)是確定的,可以選擇循環(huán)次數(shù)作為循環(huán)控制條件。如果循環(huán)次數(shù)未
知,那么可以跟具體情況選擇或其他條件作為控制條件。
循環(huán)程序有兩種結(jié)構(gòu)形式,一種是先執(zhí)行循環(huán)體,然后根據(jù)控制條件進行判斷,
不滿足結(jié)束條件則繼續(xù)循環(huán)操作,滿足條件則退出循環(huán)。這一循環(huán)類似高級語言
中的repeat-until結(jié)構(gòu)。另一類類似while-do結(jié)構(gòu),先檢查是否滿足控制條件,
滿足循環(huán)條件就執(zhí)行循環(huán)體,否則就退出循環(huán)。這兩循環(huán)結(jié)構(gòu)如圖3-7所示。
下面舉例說明。
例在一串?dāng)?shù)中找出其中的最大值和最小值,放在指定的存儲單元中。
尋找最大數(shù)和最小數(shù),可以用逐個比較來發(fā)現(xiàn),這就需要循環(huán)體來執(zhí)行,這一串
數(shù)的個數(shù)是確定的,很能夠想到以他作為循環(huán)控制條件。程序的流程圖如3-8。
通過這個程序,讀者不難確定這些數(shù)的類型和位數(shù)。
循環(huán)可以嵌套,形成多重循環(huán)結(jié)構(gòu)。多重循環(huán)程序設(shè)計的方法與單循環(huán)程序設(shè)計
大致相同。另外應(yīng)該注意的是各種循環(huán)的控制條件及循環(huán)主體不能混淆,交錯,
要層次分明。例如從外層循環(huán)進入內(nèi)層循環(huán)時,等于重新開始一次新的內(nèi)循環(huán),
初始條件等內(nèi)循環(huán)參數(shù)必須重新的設(shè)置。下面,就我們以典型的起泡法分類排序
作為一個例子,加以說明。
例有一個n個子的數(shù)組,要求變成使該數(shù)組的元素按從大到小的次序排列。
起泡算法是這樣實現(xiàn)排序的:從第一個數(shù)開始,依次對相鄰兩個數(shù)輛輛進行比較,
如果大小次序不對,則是這兩個數(shù)交換為止,反之,則不交換。這樣這樣進行了
第一遍比計較,最小的數(shù)被置于隊尾。進行第二遍比較時,只需進行n-2次第三
遍比較,最多比較到nT遍就可以實現(xiàn)程序。
圖3-9是起泡算法的一個示例,圖3-10是其流程圖。
起泡排序的內(nèi)外循環(huán)次數(shù)是已知的外循環(huán)次數(shù)是確定的,為數(shù)組長度減1,既
(n-1),
內(nèi)循環(huán)的次數(shù)安每次減1的的規(guī)律在變化。這種排序算法不管原來排序情況如
何,只要進行nT次比較,總可以達到排序的目的。但實際上,常常不需要比較
n-1次就可以完成排序。因此對算法可以進行改進,一旦完成排序,就不再進行
比較。這里設(shè)立一個標(biāo)志位,如果進行了比較,就該將該標(biāo)志位置1,如果進行
一邊比較后,沒有交換,即該標(biāo)志位仍為零,說明排序已經(jīng)完成,程序可以結(jié)束。
該今后的程序如下:
3.8字程序設(shè)計
解決實際問題時,變成通常都采用模塊化程序設(shè)計方法。這種方法把一個程序分
成多個具有任務(wù)的程序模塊,程序模塊進一步分成獨立的子模塊,分別編成,調(diào)
試,然后連接在一起,形成一個完整的程序。模塊化設(shè)計的程序易于編程,調(diào)試,
修改,程序易讀性強。而子程序結(jié)構(gòu)是模塊化的程序設(shè)計的重要工具。
子程序在匯編語言中又稱為過程,它相當(dāng)于高級語言的過程,函數(shù)或子程序。
它具有獨立的功能,在程序需要的地方可以調(diào)用它。
子程序使用時;要注意寄存器內(nèi)容的保護。由于CPU的寄存器的數(shù)量有限,子程
序使用的寄存器往往會和調(diào)用程序所用得寄存器發(fā)生沖突,破壞了調(diào)用程序中寄
存器的內(nèi)容影響從寄存器返回后的繼續(xù)處理。為了避免這種現(xiàn)象的發(fā)生,應(yīng)當(dāng)在
子程序入口八所用寄存器的內(nèi)容推入堆棧,保存起來,而在退出子程序前恢復(fù)寄
存器的內(nèi)容。
子程序使用中,要解決的一個重要問題是參數(shù)傳頌。在調(diào)用子程序時,經(jīng)常要把
參數(shù)傳送給子程序,子程序在運行以后,也常常要送回一些信息給調(diào)用程序,
報告子程序運行狀態(tài)及結(jié)果等等。這種調(diào)用程序和子程序之間的信息傳送,成
為參數(shù)傳頌,也稱為變量傳送或者過程通信。
參數(shù)傳送可以通過以下幾種渠道進行:寄存器,變量,地指表,堆棧等,下面分
別舉例說明。
3.8.1寄存器傳送參數(shù)
例把十進制ASCII字符轉(zhuǎn)換為壓縮的BCD碼數(shù)。
通常,從鍵盤上輸入的十進制數(shù)字是ASCH字符,每個數(shù)值以逗號或分號間隔,
最后一回車結(jié)束。這里假定輸入的均是4位數(shù),轉(zhuǎn)換框圖如圖3T1程序如下:
DATASEGMENT
STRINGGB'12345678998123605031',13
ERRORDB'ERROR!',13,10,'$'
BUFERDB10DUP(?)
DATAENDS
CODESEGMENT
ASSUMECS:CODE,DS:DATA
MAIN:PROCFAR
BEGIN:MOVAX,DATA
MOVDS,AX
LEABX,STRING
LEADI,BUFFER
LP:MOVAH,[BX]
INCBX
CMPAX,'O'
JBNEXT1
CMPAH'9'
JANEXT1
MOVAL,[BX]
INCBX
CMPAL,'O'
JBNEXT2
CMPAL,'9'
JANEXT2
LP1:CALLSPE1
MOV[DI],AH
INC,DI
JMPLP
NEXT1:CMPAH,''
JZLP
CMPAH,'
JZLP
CMPAH,13
JZDONE
NEXT2:LEADX,ERROR
MOVAH,9
INT21H
DONE:MOVAH,4CH
INT21H
MAINENDP
SPE1PROC
ANDAH,OFH
MOVCL,4
SHLAH,CL
ANDAL,OFH
ORAH,CL
RET
SPE1ENDP
CODEENDS
ENDBEGIN
在主程序中,得到要轉(zhuǎn)換的ASCH符通過AX寄存器傳到子程序中,子程序完成
轉(zhuǎn)換后,結(jié)果存在寄存器AH中,參數(shù)結(jié)果又通過寄存器返回主程序,在傳送參
數(shù)少的時候,利用寄存器完成參數(shù)傳送是最方便,最快捷的。
3.8.2利用變量傳送參數(shù)
例確定字符串長度,并顯示長度值。
字符串的長度不同于常用的整數(shù),系統(tǒng)并不規(guī)定于一個定值,在對字符串進行操
作
時,往往需要確定它的長度。字符串常常以回車符CR或者美元符$作為結(jié)束標(biāo)志,
因此,
從頭開始搜索字符串的結(jié)束標(biāo)志,統(tǒng)計搜索字符的個數(shù),便可以得到串長。
這里,假定串長最大不超過255。如果找不到串結(jié)束標(biāo)志,以至串長超過255,
程序
不再繼續(xù)搜索,而給出提示信息。正常時,通過DOS功能調(diào)用,顯示串長度。圖
3-12是其
流程圖。其程序如下:
DATASEGMENT
STRINGDB'Thisisastring:',13,'$'
LENGTH1DW?
CRDB13
MESSAGEDB'Thisistoolong!'
DB13,10,'$'
DATAENDS
CODESEGMENT
ASSUMECS:CODE,DS:DATA
MAINPROCFAR
BEGINMOVAX,DATA
MOVES,AX
MOVDS,AX
CALLSTRLEN;確定字符串長度
MOVDX,LENGTH1
CMPDX,1OOH
JBNEXT1;如(DX)<1OOH,
;轉(zhuǎn)去EXT1
LEADX,MESSAGE;如(DX)>=100H,顯示提示信息
MOVAH,9
INT21H
JMPNEXT2
NEXT1:MOVDH,DL;串長暫存在DH
MOVCL,4
SHRDL,CL;取串長高4位
CMPDL,9
JBELP
ADDDL,7
LP:ADDDL,30H;DL中的高4位變?yōu)锳SCH
MOVAH,6
INT21H;顯示這個ASCII符
MOVDL,DH
ANDDL,0FH
CMPDL,9
JBELP1
ADDDL,7
LP1:ADDDL,30H;DL中的低4位變?yōu)锳SCH
MOVAH,6
INT21H;顯示該ASCH符
MOVDL,'H'
MOVAH,6
INT21H
NEXT2:MOVAH,4CH
INT21H
MAINENDP
STRLENPROC
LEADI,STRING
MOVCX,OFFFFH;(CX)=-l
MOVAL,CR;(AL)=13
MOVAH,'$';(AH)='$'
CLD
AGAIN:INCCX;串長加1
CMPCX,100H
JAEDONE;串長超過255,則結(jié)束
CMP[DI],AH
JEDONE;遇'$'則結(jié)束
SCASB;搜索回車
JNEAGAIN;沒找到,返回繼續(xù)
DONE:MOVLENGTH1,CX
RET
STRLENENDP
CODEENDS
ENDBEGIN
這個程序中,主程序和子程序直接訪問模塊中的變量,通過變量,實現(xiàn)調(diào)用程序
和子
程序之間的參數(shù)傳送。
3.8.3利用地址表傳送參數(shù)
這種傳送參數(shù)的辦法是建立一張地址表,把要傳給子程序的參數(shù)存放在地址表
中,調(diào)
用程序把地址表的首地址通過寄存器傳給子程序。子程序從該地址表獲得所需參
數(shù),也把
結(jié)果存入指定的存儲單元。下面是利用這種方法傳送參數(shù)的例子。
例求一個字符串的ASCII碼的和。
DATASEGMENT
STRINGDB'Thisisastring!),13
LENGTH1DB17
SUMDW?
TABLEDW3DUP(?);保留3個參數(shù)地址
DATAENDS
CODESEGMENT
ASSUMECS:CODE,DS:DATA
MAINPROCFAR
START:MOVAX,DATA
MOVDS,AX
MOVTABLE,OFFSETSTRING
MOVTABLE+2,OFFSETLENGTH1
MOVTABLE+4,OFFSETSUM
LEABX,TABLE
CALLFINDSUM
MOVAH,4CH
INT21H
MAINENDP
FINDSUMPROC
PUSHAX
PUSHCX
PUSHSI
PUSHDI
MOVSI,[BX]
MOVDI,[BX+2]
MOVCL,[DI]
MOVDI,[BX+4]
MOVAX,0
MOVCH,AL
AGAIN:ADDAL,[SI]
ADCAH,0
INCSI
LOOPAGAIN
MOV[DI],AX
POPDI
POPSI
POPCX
POPAX
RET
FINDSUMENDP
CODEENDS
ENDSTART
3.8.4利用堆棧傳送參數(shù)
這種方法是在調(diào)用程序內(nèi)把參數(shù)或參數(shù)地址保存到堆棧中,而在子程序里從堆棧
中
取出參數(shù)或參數(shù)地址,從而實現(xiàn)參數(shù)傳送。請看下面的例子。
例從一個字符串中刪去一個字符。
相應(yīng)的程序如下:
DATASEGMENT
STRINGDB'
LENGTH1DW$-STRING
KEYDB'x';這是某個將從串中刪去的字符
DATAENDS
CODESEGMENT
ASSUMECS:CODE,DS:DATA
MAINPROCFAR
START:MOVAX,DATA
MOVDS,AX
MOVES,AX
LEABX,STRING
LEACX,LENGTH1
PUSHBX
PUSHCX;STRING和LENGTH1地址入棧
MOVAL,KEY
CALLDELCHAR;調(diào)用刪一個字符子程序
MOVAH,4CH
INT21H
MAINENDP
DELCHAPROC
PUSHBP;保存BP
MOVBP,SP;BP指向當(dāng)前棧頂
PUSHSI
PUSHDI
PUSHCX
CLD
MOVSI,[BP+4];得到LENGTH1地址
MOVCX,[SI];得到長度
MOVDI,[BP+6];得到STRING地址
REPNESCASB;重復(fù)搜索該字符
JNEDONE;沒找到,退出
MOVSI,[BP+4
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 壓花紙巾機行業(yè)市場發(fā)展及發(fā)展趨勢與投資戰(zhàn)略研究報告
- 農(nóng)村電桿申請書
- 奮斗者申請書
- 申請書領(lǐng)導(dǎo)簽名
- 市政污泥集中處置和綜合利用試驗中心工程可行性研究報告節(jié)能專
- 倉儲設(shè)備貨架生產(chǎn)建設(shè)項目可行性研究報告范文
- 2025年銅原礦采選行業(yè)深度研究分析報告
- 2025年油桶吊鉗項目投資可行性研究分析報告
- 大學(xué)貧困申請書模板
- 自動售貨機項目立項申請報告范文范本
- 小學(xué)生素質(zhì)發(fā)展報告單
- 供應(yīng)鏈行業(yè)年終述職報告總結(jié)
- 臨時用地土地復(fù)墾方案
- 肝硬化中醫(yī)護理查房
- QAV-1自我監(jiān)查確認表
- 防范非煤礦山典型多發(fā)事故60條措施培訓(xùn)
- 部編版語文二年級上冊第1單元核心素養(yǎng)教案
- 礦山機電知識培訓(xùn)課件
- GB/T 43200-2023機器人一體化關(guān)節(jié)性能及試驗方法
- 建筑四新技術(shù)全套
- 監(jiān)理項目部基本設(shè)備配置清單
評論
0/150
提交評論