匯編語(yǔ)言課件_第1頁(yè)
匯編語(yǔ)言課件_第2頁(yè)
匯編語(yǔ)言課件_第3頁(yè)
匯編語(yǔ)言課件_第4頁(yè)
匯編語(yǔ)言課件_第5頁(yè)
已閱讀5頁(yè),還剩33頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

第1章第2章第3章第4章第5章第6章第7章第8章第9章第10章

第二早

匯編語(yǔ)言程序設(shè)計(jì)

指令系統(tǒng)中的指令,在計(jì)算機(jī)內(nèi)存中,都是以二進(jìn)制編碼的形式存儲(chǔ)的,這種編碼

稱為機(jī)器碼,或者稱為機(jī)器指令.在程序運(yùn)行時(shí),指令由內(nèi)存讀入CPU,然后譯碼,

執(zhí)行.只有內(nèi)存中的機(jī)器碼,計(jì)算機(jī)才能執(zhí)行.然而,.機(jī)器碼很難記憶,使用時(shí)極

易出錯(cuò),因此,直接利用機(jī)器碼編制程序是極其困難又枯燥乏味的工作.編程的程

序,晦澀難懂,即使編程者本人,,編程后不出數(shù)日,對(duì)自己的程序,也可能不解其

慧,需仔細(xì)琢磨才能恍然大悟.這時(shí),若有詳細(xì)的程序注釋,那將會(huì)給你帶來(lái)極大

方便,免除再度疲勞之苦.

實(shí)際的需要激發(fā)人們?nèi)?chuàng)造一種符號(hào)一助記符,用他們?nèi)ゴ鏅C(jī)器碼來(lái)表示指令,

既有簡(jiǎn)單明了的詞意,一目了然,又便于理解和記憶,于是,匯編語(yǔ)言應(yīng)運(yùn)而生.

現(xiàn)在,我們可以用指令助記符和表示地址或數(shù)據(jù)等的各種符號(hào),按照規(guī)定的格式,

來(lái)編制程序,這樣的程序,稱為匯編語(yǔ)言程序.這些表示指令,地址,數(shù)據(jù)等的符號(hào)

以及有關(guān)規(guī)定,是計(jì)算機(jī)進(jìn)行:“思想”的工具,亦即計(jì)算機(jī)匯編語(yǔ)言.

匯編語(yǔ)言與具體的計(jì)算機(jī)類型有密切的關(guān)系,不同的中央處理單元,其指令系統(tǒng)

也各不相同,相應(yīng)的匯編語(yǔ)言也互不相同.與硬件關(guān)系密切的程序,或者實(shí)時(shí)性要

求很高的程序,往往采用匯編程序.

在編輯程序的支持下,匯編語(yǔ)言程序從鍵盤輸入,編輯形成匯編語(yǔ)言源程序.源程

序是用匯編語(yǔ)言的語(yǔ)句編寫的,在計(jì)算機(jī)內(nèi)部,源程序的各條語(yǔ)句是以ascii碼

表示的,存在磁盤上,又稱為源文件。它區(qū)別與機(jī)器指令之處是不能被計(jì)算機(jī)執(zhí)行,

但它可以用來(lái)顯示和打印,作為檢查和保存的檔案.

匯編語(yǔ)言源程序經(jīng)過(guò)匯編程序的語(yǔ)法檢查和翻譯,形成二進(jìn)制代碼表示的目的碼

文件.如果源程序中有語(yǔ)法錯(cuò)誤,匯編程序會(huì)指出錯(cuò)誤的類型和出錯(cuò)所在的語(yǔ)句,

以便用戶重新進(jìn)行編輯修改,再形成新的源程序.源文件和有其生成的目的碼文

件可以是一個(gè)或者是兒個(gè).

目的碼文件并不能直接上機(jī)運(yùn)行,必須經(jīng)過(guò)連接程序把它和庫(kù)文件連接在一起,

形成可執(zhí)行文件.這個(gè)可執(zhí)行文件有操作系統(tǒng)裝入計(jì)算機(jī)內(nèi)存,才能運(yùn)行.

本章介紹匯編語(yǔ)言的語(yǔ)法規(guī)則,它是匯編語(yǔ)言的“法律”,編程時(shí)必須遵循,同時(shí)

也介紹匯編語(yǔ)言程序設(shè)計(jì)方法,以共參考.

3.1宏匯編基本語(yǔ)法

ibmpc微機(jī)中,有兩個(gè)匯編程序,一個(gè)是小匯編程序asm,另一個(gè)是宏匯編程序

masm,宏匯編程序功能比較強(qiáng),并且支持宏匯編和有關(guān)的函數(shù)及偽指令,自然它需

要的存儲(chǔ)容量,比小匯編程序所需要的要稍微大一些.

3.1.1匯編語(yǔ)言程序舉例

我們通過(guò)一個(gè)例子介紹匯編語(yǔ)言的格式.這個(gè)例子的功能是把block中的正數(shù),

負(fù)數(shù)分別送到兩個(gè)緩沖區(qū)中去.程序如下:

datasegment;定義數(shù)據(jù)段

blockdb43h,Oabh;定義block變量及其數(shù)據(jù)初值

pdatadb20dup(?);定義存放正數(shù)的緩沖區(qū)

npatadb20dup(?);定義存放負(fù)數(shù)的緩沖區(qū)

dataends;數(shù)據(jù)段定義結(jié)束

codesegment;定義碼段

assumecs:code,ds:data;確定cs,ds和對(duì)應(yīng)段的關(guān)系

explprofar;定義過(guò)程

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ù)個(gè)數(shù)送ex

goon:lodsb;數(shù)據(jù)送al

testal,80h

jnzminus;判是負(fù)數(shù),則轉(zhuǎn)minus

stosb;判是正數(shù),送去存入緩沖器

jmpagain

minus:xchgbx,di;交換,使di中為負(fù)數(shù)緩沖器便址

stosb;存負(fù)數(shù)

xchgbx,di;恢復(fù)原便址寄存器

again:loopgoon;循環(huán)次數(shù)未完,則轉(zhuǎn)goon

ret;返回dos

explendp;過(guò)程定義結(jié)束

codeends;碼段定義結(jié)束

endstart;匯編結(jié)束,斷定入口地址

從這個(gè)例子,不難發(fā)現(xiàn)匯編語(yǔ)言程序通常由數(shù)據(jù)段,碼段組成.數(shù)據(jù)段存放數(shù)據(jù),

碼段存放程序指令,實(shí)現(xiàn)相應(yīng)的功能.程序結(jié)束處,必須是規(guī)定程序執(zhí)行的起始地

址,也稱為入口地址.本程序開(kāi)始執(zhí)行的地址是start.

程序語(yǔ)句行由四個(gè)部分組成,即標(biāo)號(hào)(或名字),操作碼,操作數(shù)和注釋.語(yǔ)句左邊

第?列起為標(biāo)號(hào)區(qū),句末分號(hào)后的為注釋區(qū),中間的部分為操作數(shù)區(qū).按照這種格

式書寫并輸入計(jì)算機(jī),既是程序的要求,也使人閱讀時(shí)清清楚楚,賞心悅目.

3.1.2匯編語(yǔ)言程序結(jié)構(gòu)

匯編語(yǔ)言源程序通常由一個(gè)或兒個(gè)程序模塊組成,每個(gè)模塊包括數(shù)據(jù)段,堆棧段

和若干個(gè)代碼段.有時(shí)程序中可以不設(shè)堆棧段,而利用系統(tǒng)中已設(shè)定的堆棧段.代

碼段中有若干個(gè)過(guò)程,過(guò)程又稱子程序。過(guò)程中的語(yǔ)句分為兩類,兩類是指示性

語(yǔ)句,另一類是指示性語(yǔ)句.指示性語(yǔ)句是計(jì)算機(jī)能執(zhí)行的指令,而指示性語(yǔ)句,

計(jì)算機(jī)并不能執(zhí)行。匯編時(shí),依據(jù)指示性語(yǔ)句的規(guī)定,匯編程序?qū)υ闯绦蜻M(jìn)行相

應(yīng)的處理操作,進(jìn)行諸如定義數(shù)據(jù)、分配存儲(chǔ)區(qū)、指示程序開(kāi)始和結(jié)束等服務(wù)性

工作,以減輕編程員的負(fù)擔(dān)。指示性語(yǔ)句又成偽指令。

這里,用等式表示程序和過(guò)程的結(jié)果內(nèi)容:

程序={塊[數(shù)據(jù)段,堆棧段,代碼段(過(guò)程1,過(guò)程2,……)],快……}

過(guò)程={指示性語(yǔ)句,指令性語(yǔ)句}

指示性語(yǔ)句的格式如下:

[名字][偽指令][操作數(shù)][;注釋]

例如:

SUMPROCFAR;定義一個(gè)過(guò)程

SUMENDP;過(guò)程定義結(jié)束

指令性語(yǔ)句的格式為:

[標(biāo)號(hào):][前綴][指令助記符][操作數(shù)][;注釋]

例如:

LP1:MOVBX,OFFSETDAREA;DAREA的地址送BX

語(yǔ)句中名字和符號(hào),又稱為符標(biāo)識(shí)符,是程序員自己確定的,它不允許與指令助

記符或偽指令同名,也不允許有數(shù)字打頭,字符個(gè)數(shù)不得超過(guò)31個(gè)。

3.1.3數(shù)據(jù)項(xiàng)與表達(dá)式

操作數(shù)是指令和偽指令中很重要的一部分內(nèi)容,它可以用寄存器、存儲(chǔ)器單元或

數(shù)據(jù)項(xiàng)來(lái)表示。其中,數(shù)據(jù)項(xiàng)是最靈活多變的,它有三種形式:常量、標(biāo)號(hào)、變

量。常量、變量和標(biāo)號(hào)以及他們的表達(dá)式都可以作為操作數(shù)使用。下面分別介紹。

1常量

常量包括數(shù)字常量和字符常量?jī)煞N。

(1)數(shù)字常量

二進(jìn)制常量——以字母為結(jié)尾的數(shù)為二進(jìn)制數(shù)。例如,10111010。

十進(jìn)制常量——以字母結(jié)尾或沒(méi)有字母結(jié)尾的數(shù)為十進(jìn)制數(shù)。例如8914,2376

十六進(jìn)制常量——以字母結(jié)尾的數(shù)為十六進(jìn)制數(shù)。例如1在匯編程序中,凡是以

字母開(kāi)始的十六進(jìn)制數(shù),必須在前面加上數(shù)字0,以避免和表示符相混淆。

(2)字符串常量

以單引號(hào)內(nèi)一個(gè)或多個(gè)ASCH字符構(gòu)成字符串常量。匯編程序把他們翻譯成對(duì)應(yīng)

的ASCH碼值,一個(gè)字符對(duì)應(yīng)一個(gè)字節(jié)。例如,字符串常量,AB,和'C,在匯

編時(shí)分別被翻譯成4142H和43Ho

2.標(biāo)號(hào)

標(biāo)號(hào)是存放某條指令的存儲(chǔ)單元的符號(hào)地址,通常他用作條件轉(zhuǎn)移,無(wú)條件轉(zhuǎn)移

指令或調(diào)用指令的目標(biāo)操作數(shù)。

標(biāo)號(hào)是由標(biāo)識(shí)符即標(biāo)號(hào)后面跟一個(gè)冒號(hào)來(lái)定義的。例如:

START:MOVAX,DATA

LP1:MOVCX,COUNT

這兩條語(yǔ)句分別定義了兩個(gè)標(biāo)號(hào)START和LP1,他們可以供轉(zhuǎn)移指令,循環(huán)指令

或調(diào)用指令當(dāng)作目標(biāo)操作數(shù)來(lái)使用。

標(biāo)號(hào)作為存儲(chǔ)單元的符號(hào)地址,他具有3種屬性:段值,偏移量和類型。標(biāo)號(hào)的

段值,偏移量屬性分別指它的段地址和偏移地址,而標(biāo)號(hào)的類型分NEAR和FAR

兩種。

NEAR類型的標(biāo)號(hào)是指標(biāo)號(hào)所在的語(yǔ)句和調(diào)用指令或轉(zhuǎn)移指令在同一個(gè)碼段中,

執(zhí)行調(diào)用指令或轉(zhuǎn)移指令時(shí),只需要把標(biāo)號(hào)的偏移地址送給IP,就可以實(shí)現(xiàn)調(diào)

用或轉(zhuǎn)移,并不需要改變碼段段址。

而FAR和NEAR類型不同,F(xiàn)AR類型標(biāo)號(hào)所在語(yǔ)句與其調(diào)用指令或轉(zhuǎn)移指令不

在用一碼段中,執(zhí)行調(diào)用指令或轉(zhuǎn)移指令時(shí),不僅需要改變偏址IP的值,而且

需要改變段值CS的值。這是段間的調(diào)用或轉(zhuǎn)移。

3.變量

變量是內(nèi)存中的數(shù)據(jù)區(qū),由若干個(gè)存儲(chǔ)單元構(gòu)成,內(nèi)存中的內(nèi)容是可以修改的,

因此,變量的值也是可以哦改變的。變量在程序中,作為存儲(chǔ)器操作數(shù)來(lái)使用。

變量具有3中屬性:

(1)段值(SEGMENT)——變量定義所在段的段地址。為了確保匯編程序能找

到該變量,應(yīng)在偽指令(ASSUME)中加以說(shuō)明,把其段值放在一個(gè)短寄存器中,

如CS,DS,ES或SS。

(2)偏移量(OFFSET)一—變量的地址和變量所在段的起始地址之間的偏移量。

(3)類型(TYPE)——變量的類型定義了該變量存儲(chǔ)區(qū)內(nèi)每個(gè)數(shù)據(jù)所占內(nèi)存單

元的字節(jié)數(shù),如字節(jié),字,雙字類型變量分別站用內(nèi)存1,2,4個(gè)字節(jié)單元。

變量定義的格式如下:

[變量名],[數(shù)據(jù)定義偽操作],[表達(dá)式]

變量名有字母打頭,最多允許31個(gè)字符,定義以后,凡是用到這個(gè)變量名時(shí),

必須注意其三個(gè)屬性。數(shù)據(jù)定義偽操作將該變量名定義成某種類型的變量(數(shù)據(jù)

定義偽操作在以后敘述)。而表達(dá)式則確定了變量的初值和這個(gè)變量數(shù)據(jù)區(qū)的大

小,它允許采用數(shù)值表達(dá)式或地址表達(dá)式。

變量使用時(shí),要注意以下幾點(diǎn):

(1)變量類型與指令要求的操作數(shù)類型相符。例如,MOVAL,VARI指令中,

要求VARI應(yīng)該是字節(jié)類型的,才與AL的類型匹配。而指令MOVBX,VAR2則要

求VAR2應(yīng)該定義成字類型的變量。

(2)變量的編址。變量定義以后,變量名僅僅對(duì)應(yīng)這個(gè)數(shù)據(jù)區(qū)的首地址。若這

個(gè)數(shù)據(jù)區(qū)中有若干個(gè)數(shù)據(jù)項(xiàng),在對(duì)其后面的數(shù)據(jù)項(xiàng)進(jìn)行操作時(shí),其地址需要改變。

例如,欲求變量XY數(shù)據(jù)區(qū)中20個(gè)字的和,在加下一個(gè)數(shù)據(jù)項(xiàng)時(shí),地址應(yīng)該進(jìn)行

修改,以指向那個(gè)數(shù)據(jù)項(xiàng)。具體程序段如下:

XYDW20DUP(?)

MOVAX,XY+38;送最后一個(gè)字給AX

MOVBX,38

LP1:SUBBX,2;偏址修改

ADDAX,XY[BX];求和

CUPBX,0;判是否是第一個(gè)數(shù)字

JNELP1;不是,則幾需求和

(3)變量的斷址。指令中的操作數(shù)的斷址往往不直接表示出來(lái),而是隱含的,

或者稱為默認(rèn)的或缺省的。變量使用時(shí),其段屬性應(yīng)與所在指令的缺省段寄存器

相符。如若不符,應(yīng)該把段地址直接表示出來(lái),這種表示方法,稱為跨段前綴。

跨段前綴可以用段寄存器或段名來(lái)表示。例如:

MOVAX,ES:[BX]

MOVAX,DATA:[DI]

4表達(dá)式

匯編程序允許使用表達(dá)式。然而,表達(dá)式并不是指令,它本身不能執(zhí)行。程序被

匯編時(shí),匯編程序?qū)Τ绦蛑械谋磉_(dá)式進(jìn)行相應(yīng)的運(yùn)算,其運(yùn)算結(jié)果是一個(gè)值。因

此,在程序被執(zhí)行時(shí),表達(dá)式本身已經(jīng)是一個(gè)有確定值的操作數(shù)。

變達(dá)式中的運(yùn)算有三類運(yùn)算符一一算術(shù)運(yùn)算符、邏輯運(yùn)算符和關(guān)系運(yùn)算符來(lái)表

/J、.O

(1)算術(shù)運(yùn)算符

有+,*,/,MOD五種算術(shù)運(yùn)算符,前面4種是最常見(jiàn)到的加、減、乘、除、

四則運(yùn)算符,而MOD是表示求兩個(gè)數(shù)相除以后的余數(shù)。例如,23M0D7其結(jié)果是

2,即23除以7,其余數(shù)是2。

算術(shù)運(yùn)算符用于數(shù)字表達(dá)式,其結(jié)果仍是數(shù)字。

算術(shù)運(yùn)算符也可以用于地址表達(dá)式,但其應(yīng)用范圍受到一定的限制,那就是地址

表達(dá)式的運(yùn)算必須有明確的物理意義,其運(yùn)算結(jié)果才有效,否則該地址表達(dá)式是

錯(cuò)誤的。

通常,地址表達(dá)式中使用加或者減運(yùn)算。地址加或者減一個(gè)數(shù)字量,表示對(duì)原地

址偏移該數(shù)字的若干個(gè)單元的地址。例如,VAR+2表示變量VAR的地址加上2

得到的和作為新的存儲(chǔ)單元的地址。同一段中兩個(gè)存儲(chǔ)單元地址之差,表示他們

之間的地址偏移量,或者有時(shí)表示這兩個(gè)存儲(chǔ)單元之間有多少個(gè)字節(jié)。而不同段

址的兩個(gè)偏移地址的加或者減是沒(méi)有物理意義的,兩個(gè)地址相乘或相除同樣也是

沒(méi)有物理意義的。例如,若要把字?jǐn)?shù)祖阿惹第九個(gè)字傳到AX寄存器,用指令可

以這樣表示:

MOVAX,VAR+(9T)*2

其中,VAR是該數(shù)組的首地址,(9T)*2是第9個(gè)字的地址與首地址的偏移量。

(2)邏輯運(yùn)算符

有AND,OR,NOT和XOR四種邏輯運(yùn)算符,邏輯運(yùn)算是按位操作的,邏輯運(yùn)算符

只能用于數(shù)字表達(dá)式,不能用于存儲(chǔ)器地址表達(dá)式。例如:

MOVAL,OADHANDOCCH

匯編時(shí),計(jì)算上式中右邊邏輯表達(dá)式,得到結(jié)果為8cH,這樣就轉(zhuǎn)化為指令

MOVAL,8CH

表達(dá)式VAROR80H是無(wú)效的,因?yàn)檫壿嬤\(yùn)算符不能用于地址表達(dá)式。

那么,指令OUTPORTANDFEH,AL是否有效呢?答案是肯定的,有效。因?yàn)镻ORT

是1個(gè)字節(jié)的數(shù)字,而不是一個(gè)變量,盡管它名義上是作為外設(shè)口的地址,實(shí)

際上匯編程序認(rèn)為它是一個(gè)數(shù)字,PORT是?個(gè)數(shù)字表達(dá)式,因此允許使用邏輯

運(yùn)算符。該指令在匯編時(shí),若PORT是偶數(shù),則表達(dá)式結(jié)果與原端口號(hào)相同,若

PORT是奇數(shù)時(shí),該指令的輸出端口為一偶數(shù),比PORT端口號(hào)小1。

這里需要提醒的是這些邏輯運(yùn)算符是用于數(shù)字表達(dá)式的運(yùn)算符,并不是邏輯運(yùn)算

指令的操作碼。前者是匯編程序在進(jìn)行匯編時(shí)處理的,而后者是在程序運(yùn)行時(shí)執(zhí)

行的。

(3)關(guān)系運(yùn)算符

有EQ,NE,LT,GT,LE,GE六種關(guān)系運(yùn)算符。這些關(guān)系運(yùn)算符分別表示兩個(gè)操

作數(shù)是否相等,不等,小于,大于,小于等于和大于等于。關(guān)系運(yùn)算的兩個(gè)操作

數(shù)必須都是數(shù)字或者都是同一段內(nèi)的存儲(chǔ)器地址。關(guān)系運(yùn)算的結(jié)果是一個(gè)邏輯

值,結(jié)果為真,邏輯值是OFFFFH;結(jié)果為假,值為0。例如:

MOVAX,VARIGTVAR2

如果VARI地址大于VAR2,則匯編結(jié)果應(yīng)該是:

MOVAX,OFFFFH

否則,匯編結(jié)果就成為:

MOVAX,0000H

數(shù)字表達(dá)式比較容易理解,而地址表達(dá)式比較復(fù)雜。

地址表達(dá)式由變量,標(biāo)號(hào),常量,基址,變址寄存器以及相關(guān)的運(yùn)算符組成,它

表示了存儲(chǔ)器的地址。地址表達(dá)式有三種屬性,即段值,偏移量,類型。地址表

達(dá)式的段值,偏移量即是其段地址和偏移地址。而類型則有字節(jié),字和雙字類型,

以及近(NEAR)和遠(yuǎn)(FAR)類型兩種,前者和數(shù)據(jù)的存儲(chǔ)單元相對(duì)應(yīng),后者與

程序轉(zhuǎn)移或調(diào)用的目標(biāo)地址相對(duì)應(yīng)。

和地址表達(dá)式有關(guān)的運(yùn)算符,除了前面所提及的,還有下面兩種操作符。

(1)類型操作符一一PTR程序中對(duì)變量或標(biāo)號(hào)定義后,變量或標(biāo)號(hào)的屬性便確

定了。也就是有它的段址,偏址和類型。但在實(shí)際使用時(shí),可能會(huì)出現(xiàn)與原先定

義的類型不匹配的情況,需要臨時(shí)加以調(diào)整。PTR操作符給地址表達(dá)式臨時(shí)賦予

一個(gè)新的類型,而地址表達(dá)式的斷值,偏移量屬性不便。其操作的格式如下:

類型地址表達(dá)式

其中的類型可以是或

例如,給已定義為字:

varidw?

那么,只能在字操作令中使用vari這個(gè)變量,如movax,varl時(shí)合法的。但是,

要把varl當(dāng)作字操作數(shù)來(lái)使用,便是非法的,指令

movvari,al

會(huì)出現(xiàn)類型不配的錯(cuò)誤,而指令

movbyteptrvarl,al

則合法的。操作符ptr產(chǎn)生了一個(gè)新的地址操作數(shù),該操作數(shù)的段地址和偏移地

址與varl相同,而類型為字節(jié)型,不是原先定義的字類型。

若標(biāo)號(hào)next原來(lái)定義是near類型,現(xiàn)在另一個(gè)段中的程序要轉(zhuǎn)移到此next處,

那么采用指令

jmpfarptrnext

來(lái)實(shí)現(xiàn)段間的轉(zhuǎn)移。

(2)樹(shù)枝返回操作符——segoffset有時(shí),并不希望對(duì)變量的內(nèi)容進(jìn)行處理,

而需要這個(gè)變量的地址以便量進(jìn)行操作;有時(shí),并不希望轉(zhuǎn)移到某個(gè)標(biāo)號(hào)定義

的目標(biāo)地址去,而是需要對(duì)這個(gè)標(biāo)號(hào)的地址進(jìn)行處理。在這兩種情況下,需要利

用seg和offset這兩個(gè)數(shù)值返回操作符,他的操作格式如下:

seg變量或標(biāo)號(hào)

offseg變量或標(biāo)號(hào)

seg操作符返回變量或者標(biāo)號(hào)的段址。而offseg操作符返回變量或者標(biāo)號(hào)的偏

移量。

例如:

movaxmsegvarname

movbx,offsegvarname

分別得到varname段址和對(duì)短起始地址的偏移量,傳送給ax和bx寄存器。

32指示性語(yǔ)句

指示性語(yǔ)句.偽操作語(yǔ)句。偽操作不是計(jì)算機(jī)指令系統(tǒng)的一部分,而是匯編程序

提供源程序的服務(wù)工具,用以完成會(huì)變得輔助性工作,諸如變量定義,符號(hào)賦值,

程序守為標(biāo)志等。Ibm宏匯編提供以下兒類操作語(yǔ)句:變量定義語(yǔ)句:符號(hào)賦值

語(yǔ)句;斷定義語(yǔ)句;過(guò)程定義語(yǔ)句;??於x語(yǔ)句。

下面對(duì)這兒類為操作的常用部分加以敘述。書中沒(méi)有涉及的偽操作,讀者需要是

可以查閱手冊(cè)。

3.2.1變量定語(yǔ)句

變量定義語(yǔ)句為變量分配若干個(gè)初值。這一類操作的格式為:

[變量名]助記符操桌數(shù)。?!僮罃?shù)[;注釋]

其中變量子段名用符號(hào)地址表示,分配的春儲(chǔ)單元的第一個(gè)字節(jié)的偏移地址是這

個(gè)變量名的值。這個(gè)變量名字段也可以沒(méi)有,表示只分配若干個(gè)存儲(chǔ)單元。

注釋子段用來(lái)對(duì)該偽朝作做一些說(shuō)明,如它的功能等。

超作數(shù)子段可以有若個(gè)個(gè)操捉數(shù),偽操作把這些數(shù)據(jù)存入指定的存儲(chǔ)單元。這里

操作數(shù)可以是指定的數(shù)值表達(dá)式、ASC字符穿、地址表達(dá)式。助記符字段是定義

變量的偽操作,常用的有DB,DW,DD等兒種。

DB偽操作用來(lái)定義字節(jié)形變量,其中的每個(gè)操作數(shù)都占有一個(gè)字節(jié)存儲(chǔ)單元,

每個(gè)操作數(shù)的值不操過(guò)255。

DW偽操作用來(lái)定義字形變量,其中的每個(gè)操作數(shù)都占有兩個(gè)字節(jié),字的低位字

節(jié)在第一個(gè)字節(jié)地址單元中,字的低位字節(jié)在第二個(gè)字節(jié)地址單元中,簡(jiǎn)單的說(shuō),

就是低位在前、高位在后、或低位低地址、高位高地址。

DD偽操作用來(lái)定義雙字型變量,其中的每個(gè)操作數(shù)都占有兩個(gè)字,雙字的最低

位字節(jié)在第一個(gè)字節(jié)地址單元中,次低位字節(jié)在第二個(gè)字節(jié)地址單元中,次高位

字節(jié)在第三個(gè)字節(jié)地址單元中,高位字節(jié)在第四個(gè)字節(jié)地址單元中。

例操作數(shù)是常數(shù)或者表達(dá)式。

BYTE_VARDB12,4,12H

WORD_VARDW100H,-2,10*6

DW_VARDDOFEFDH

匯編程序在匯編時(shí),根據(jù)表達(dá)式可以求得一個(gè)常數(shù),把數(shù)據(jù)結(jié)果存入存儲(chǔ)器,如圖

3-1.

例操作數(shù)可以是字符串,如:

STRINGDB'OK!'

CHARDB'AB'

WARDDW'AB'

匯編后,存儲(chǔ)器的存儲(chǔ)情況如圖3-2所示.

例操作數(shù)字段用符號(hào)?來(lái)表示,即保留存儲(chǔ)空間,不存入起始數(shù)值.操作數(shù)字段

也可以用復(fù)制操作符DUP復(fù)制某些數(shù)據(jù),如:

ARRAY1DB4DUP(?)

ARRAY2DB10DUP(0,1)

DUP前面的數(shù)據(jù)指定括號(hào)中的操作數(shù)的重復(fù)次數(shù),它可以是一個(gè)表達(dá)式.匯編后,

存儲(chǔ)器的存儲(chǔ)情況如圖3-3.

3.2.2符號(hào)賦值語(yǔ)句

程序中,有時(shí)多次出現(xiàn)同一個(gè)表達(dá)式,為了方便起見(jiàn),用賦值偽操作給表達(dá)式賦予

一個(gè)符號(hào)名,以后,凡用到該表達(dá)式的地方都可以用這個(gè)符號(hào)名來(lái)表示,這樣,意

義清楚,修改容易.格式如下:

符號(hào)名EQU表達(dá)式

其中表達(dá)式可以是任何有效的操作數(shù),可以是任何結(jié)果為常數(shù)的表達(dá)式,也可以

是助組記符.例如:

COUNTEQU256

BEQU[BP+8]

P8EQUDS:[BP+8]

LPNEQULP1+12H;給^^賦地址表達(dá)式

SSBEQUSTOSB

EQU語(yǔ)句的表達(dá)式中,如果有變量或符號(hào)出現(xiàn),則在該語(yǔ)句前后必須給出它們的

定義,表達(dá)式才有效,否則匯編程序?qū)⑻崾境鲥e(cuò).例中的第四個(gè)語(yǔ)句的LP1應(yīng)該在

次句前加以定義.

符號(hào)用EQU語(yǔ)句賦值后,不能重新賦值.除非用PURGE語(yǔ)句解除這些賦值關(guān)系,符

號(hào)才能賦新的值.PURGE語(yǔ)句的格式為:

PURGE符號(hào)1,符號(hào)2,…,符號(hào)n,

而另一個(gè)與EQU語(yǔ)句功能類似的語(yǔ)句,即=偽操作.=偽操作允許給符號(hào)賦一個(gè)常

量,或者結(jié)果是常數(shù)的表達(dá)式,并且允許對(duì)符號(hào)重新賦值.例如:

EMP=16

EMP=17

EMP=EMP+1

3.2.3段定義語(yǔ)句

前面我們已經(jīng)講過(guò),8086和8088的存儲(chǔ)器的物理地址由段地址和偏移地址組合

而成.程序運(yùn)行時(shí),程序的指令和變量都存在某個(gè)段內(nèi).因此,匯編程序按段來(lái)組

織程序和數(shù)據(jù),變量.與段有關(guān)的主要偽操作有SEGMENT;ENDS;ASSUME;ORG.

段定義的格式如下:

segnameSEGMENT

segnameENDS

每個(gè)段必須有一個(gè)名字,每個(gè)段定義由SEGMENT開(kāi)始,到ENDS結(jié)束,兩者少一不可,

并且其語(yǔ)句中的名字必須相同,否則,匯編程序無(wú)法辨認(rèn).省下的部分,數(shù)據(jù)段,附

加段和堆棧段來(lái)說(shuō),一般是變量,符號(hào)定義等偽操作,而對(duì)于代碼段則是指令及有

關(guān)偽操作.定義段之后,還需要用ASSUME偽操作語(yǔ)句,以確定段和段寄存器的關(guān)

系.其格式為:

ASSUMEseg-reg;segname[,,,,]

其中段寄存器名必須是CS,DS,ES,SS中的一個(gè),而段名是由SEGMENT和ENDS定

義的段中的段名.欲取消前面的ASSUME語(yǔ)句確定的段與段寄存器的關(guān)系,可采

用ASSUMENOTHING語(yǔ)句.例如:

datalSEGMENT

XIDB?

X2DW?

X3DD?

datalENDS

extralSEGMENT

ylDB?

y2DW?

y3DD?

extralENDS

stacklSEGMENT

DW100HDUP(?)

TopEQUTHISWORD;THIS是個(gè)運(yùn)算符,它建立一個(gè)新的存儲(chǔ)器地址操作數(shù),

stacklENDS;其地址為匯編時(shí)的當(dāng)時(shí)值,類型由THIS后的項(xiàng)指定.

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ǔ)句確定了短與段寄存器的對(duì)應(yīng)關(guān)系,供匯編時(shí)使用,而段地址裝入段寄

存器,即段寄存器的賦值,還需要代碼中的MOV指令來(lái)完成.不過(guò),碼段寄存器例

外,它是在程序初始化時(shí),由系統(tǒng)程序完成的,不需要也不允許用戶給CS賦值.用

戶程序模塊可以存放在一個(gè)或幾個(gè)碼段中,根據(jù)需要定.

SEGMENT偽操作還可以增加一些說(shuō)明,格式如下:

SegnameSEGMENT[align-type][combine-type][,class']

這三種類型說(shuō)明分別敘述如下:

(1)定位類型(align-type)

PARA該段的起始地址從段的邊界開(kāi)始,也就是段地址的最低位必定為0(十六進(jìn)

制數(shù)表示).通常隱含.

BYTE該段可以從任何有效地址開(kāi)始.

WORD該段的起始地址必須是偶數(shù),即從字的邊界開(kāi)始.

PAGE該段的起始地址從頁(yè)邊界開(kāi)始,即段地址最低兩個(gè)十六進(jìn)制數(shù)位為0(一頁(yè)

為256字節(jié)).

(2)組合類型(combine-type)

PUBLIC規(guī)定連接時(shí)該段要和其他具有相同的段名的段連接在一起,形成一個(gè)段,

連接的次序在調(diào)用LINK程序時(shí)由用戶指定.

COMMON規(guī)定連接時(shí)該段和其他同名段具有相同的起始地址.因而產(chǎn)生覆

蓋.COMMON的連接長(zhǎng)度是同名段中的最大長(zhǎng)度.

ATexpression規(guī)定表達(dá)式計(jì)算結(jié)果的16位二進(jìn)制值為段的起始地址.但不能用

于指定代碼段,而用于固定地址的數(shù)據(jù)段,如ROM中的數(shù)據(jù)區(qū),或存儲(chǔ)區(qū)中的向量

表.

STACK規(guī)定該段在運(yùn)行時(shí)是堆棧段的一部分.

MEMORY規(guī)定該段定在所有其他連接段的后面.

(3)類別('class')

它是一個(gè)名字,用于連接時(shí)組成同名段組.

偽操作指令ORG語(yǔ)句規(guī)定了程序段或數(shù)據(jù)塊在該段內(nèi)的起始地址,其格式為

ORGexpression

其中表達(dá)式expression的值即為段內(nèi)的起始地址或偏移地址,從此地址起連續(xù)

存放程序或數(shù)據(jù).

3.2.4過(guò)程定義語(yǔ)句

一個(gè)過(guò)程具有某一種功能,形成獨(dú)立的程序塊,它是匯編程序的基本單位.

過(guò)程定義的格式如下:

procedure-namePROC

RET

procedure-nameENDP

過(guò)程定義的偽操作PROC和ENDP必須成對(duì)出現(xiàn).在過(guò)程的首尾處,必須有過(guò)程名起

頭.過(guò)程結(jié)束處往往有RET語(yǔ)句,以返回調(diào)用它的程序處.有時(shí)RET語(yǔ)句也可以出

現(xiàn)在過(guò)程中間.過(guò)程至少有一個(gè)入口和出口,以供進(jìn)入和脫離該程序.

按上面定義,只能在該程序的同一碼段中被調(diào)用.過(guò)程應(yīng)賦予FAR的屬性,格式如

下:

procedure-namePROCFAR

procedure-nameENDP

調(diào)用過(guò)程和從過(guò)程返回有兩種情況:段內(nèi)的和短間的.

段內(nèi)的調(diào)用和返回指令執(zhí)行時(shí),推入堆棧和退出堆棧的僅僅是應(yīng)該返回處的段內(nèi)

的地址偏移量.

段間的調(diào)用和返回指令執(zhí)行時(shí),推入堆棧和退出堆棧的僅僅是應(yīng)該返回處的段地

址和段內(nèi)偏移量.

在定義時(shí),可以用NEAR屬性顯式地表示:

procedure-namePROCNEAR

procedure-nameENDP

3.2.5程序模塊定義

每一個(gè)程序模塊的開(kāi)始,往往要用NAME或TITLE為其取一個(gè)名字,模塊結(jié)束,則需

要用END偽操作來(lái)告知匯編程序,在遇到END語(yǔ)句時(shí)結(jié)束匯編.

NAME的格式為:

NAMEmodule-name

匯編程序把NAME后面的module-name作為模塊的名字,這個(gè)名字不允許使用保留

字,可以使用標(biāo)識(shí)符.

TIYLE的偽操作,格式是:

TITLEtext

它為清單的每一頁(yè)指定打印的標(biāo)題.text

中最多允許60個(gè)字符.若無(wú)NAME偽操作,則把text

中的前6個(gè)字符作為模塊名.若既無(wú)NAME又無(wú)TITLE偽操作,則就吧源文件名作

為模塊名.

知NAME和TITLE偽操作并不是必須的.

但每個(gè)模塊的結(jié)束,必須要有END偽操作,格式為:

END[label]

其中,可選的標(biāo)號(hào)指示程序開(kāi)始執(zhí)行的起始地址。如果若干個(gè)個(gè)程序??煜嗦?lián)接,

那么只有住程序模快需要使用帶入標(biāo)號(hào)的語(yǔ)句,而其他程序模塊是被調(diào)用的,

不能使用帶入標(biāo)號(hào)的語(yǔ)句,只需要。

下面是一個(gè)兩個(gè)數(shù)差的絕對(duì)值的程序。

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

這個(gè)有一個(gè)程序模快組成,他從為操作開(kāi)始,為操作結(jié)束。語(yǔ)句制定了該程

序的入口地址,此入口地址在程序在該程序中正好是第一條執(zhí)行指令的地址,這

個(gè)程序丁宜樂(lè)了一個(gè)數(shù)據(jù)段和一個(gè)媽段,碼段中紙包裹一個(gè)過(guò)程,過(guò)程結(jié)束時(shí),

通過(guò)調(diào)用的的功能,返回,程序結(jié)束運(yùn)行。

3.3匯編語(yǔ)言程序設(shè)計(jì)程序

第二章介紹了指令系統(tǒng),結(jié)合指令也給出了一些程序段例子,本章的第一二節(jié)由

介紹了紅會(huì)變得基本語(yǔ)法和偽指令。有了這些基礎(chǔ)知識(shí),就不難進(jìn)行匯編語(yǔ)言的

程序設(shè)計(jì)。

從下一節(jié)起,介紹匯編語(yǔ)言程序設(shè)計(jì)的主要方法。這里次先介紹與匯編語(yǔ)言程序

有關(guān)的問(wèn)題,以便在程序設(shè)計(jì)之前,引起大家的注意,少哦組一些彎路。

3.3.1程序的質(zhì)量標(biāo)準(zhǔn)

再編程序時(shí),首先要有一個(gè)質(zhì)量觀念,要編制質(zhì)量高的程序,而不僅僅是完成任

務(wù)。在進(jìn)行學(xué)習(xí)時(shí),要逐步養(yǎng)成良好的編程習(xí)慣。如同寫文章,撰寫的作品千只

百態(tài)一樣,用計(jì)算機(jī)敘述某個(gè)問(wèn)題,也即編程,同樣千差萬(wàn)別。衡量程序的質(zhì)量,

通稱有四個(gè)標(biāo)準(zhǔn):

(1)程序正確完整;

(2)程序易讀性;

(3)程序的執(zhí)行時(shí)間;

(4)程序所占內(nèi)存大小及程序行數(shù)。

其中,第一條是主要的,最基本的。往往有些程序基本功能是正確的,但隱藏著

一些問(wèn)題,或者在某些情況下執(zhí)行是正確的,而在另外的情況下程序運(yùn)行的結(jié)果

是不對(duì)的。程序的一讀性對(duì)軟件的維護(hù)和軟件設(shè)計(jì)的合作是大有裨益的,因此已

開(kāi)始就養(yǎng)成良好的編程習(xí)慣,編程思路要清楚,畫一個(gè)流程圖,在程序前部隊(duì)變

量和算法加以說(shuō)明,在程序中對(duì)有關(guān)語(yǔ)句加上注釋。程序的執(zhí)行時(shí)間對(duì)于實(shí)時(shí)處

理的問(wèn)題環(huán)重要的。程序所占內(nèi)存大小對(duì)于復(fù)雜的大程序來(lái)說(shuō),也不能等閑視之,

而考慮到軟件的開(kāi)發(fā)成本,程序的語(yǔ)句則是一個(gè)很重要的因素。

3.3.2

(1)把實(shí)際問(wèn)題抽象,提煉成數(shù)學(xué)模型。

(2)確定解決該數(shù)學(xué)模型的算法.

(3)程序模塊分析。在分析復(fù)雜的實(shí)際問(wèn)題時(shí),往往需要把它分成若干功能塊,畫

出層次圖,確定各塊間的通信。對(duì)于簡(jiǎn)單的問(wèn)題,僅僅一個(gè)模塊足以完成其任務(wù),

就無(wú)須模塊分析.

⑷畫出模塊程序圖.

⑸分配內(nèi)存工作單元和寄存器.

(6)根據(jù)流程圖編制程序.

(7)上機(jī)調(diào)試,進(jìn)行修改,最后檢測(cè)通過(guò).

編制過(guò)程的第一步,數(shù)學(xué)抽象,是很重要的一環(huán),它關(guān)系到全局,不可輕視.實(shí)際

工作中,因?yàn)槌橄蟛粶?zhǔn)確,以致返工的是屢見(jiàn)不鮮.確定算法亦是關(guān)鍵的一步,它

與程序質(zhì)量的高低密不可分,它決定了程序的復(fù)雜程度和執(zhí)行時(shí)間的長(zhǎng)短.其后

的模塊分析,編制流程圖和程序,也往往要通過(guò)調(diào)試進(jìn)行相應(yīng)的修正.

3.3.3程序流程圖

程序流程圖是一種算法表達(dá)工具,它根據(jù)算法,將結(jié)局問(wèn)題的思路和方法用字符

和圖形表示出來(lái),確定程序的結(jié)構(gòu)和程序的流向.

對(duì)于處學(xué)者,程序流程圖是比不可少的工具.對(duì)于熟練的編程者,在編制復(fù)雜的程

序時(shí),仍然少不了流程圖的支持。它便于編制程序,便于調(diào)試程序,有利于減少程

序的錯(cuò)誤,提高程序效率.

本書的流程圖,采用國(guó)際標(biāo)準(zhǔn),它與我國(guó)國(guó)標(biāo)也是基本一致的。所用主要的符號(hào)

如下:

(1)矩形框表示各種處理的功能,框中用簡(jiǎn)明的語(yǔ)言表明所完成的處理功能.例

如執(zhí)行一個(gè)加法操作.這種處理有一個(gè)入口和一個(gè)出口,有箭頭表示.

(2)菱形框表示判斷,框內(nèi)表明判斷的條件.它有一個(gè)入口,但可以有若干個(gè)出

口,分別用箭頭表示。在各個(gè)出口處表明該出口的條件,例如條件滿足用y表示,

條件不滿足時(shí)用n表示.

(3)特定的方框表示特定處理,通常表示子程序,模塊??騼?nèi)表明程序名或模塊名,

框縱邊為雙數(shù),形如

(4)端點(diǎn)框六邊形表示程序流程的起點(diǎn),扁圓形框表示程序的終點(diǎn).

(5)流線帶箭頭的直線,表示程序的流向,它連接程序的各個(gè)流程圖,新的圖表

正向流線不帶箭頭,反向流線帶箭頭.

3.4數(shù)據(jù)輸入和輸出

程序通常要對(duì)數(shù)據(jù)進(jìn)行處理,而后輸出結(jié)果.那么所需要的數(shù)據(jù)來(lái)自何處?他們可

能;來(lái)自:1程序的數(shù)據(jù)段,編程時(shí)預(yù)先設(shè)定;2磁盤,數(shù)據(jù)以數(shù)據(jù)文件的形式存在

盤上;3外設(shè),例如A/D轉(zhuǎn)換,把模擬信號(hào)轉(zhuǎn)成數(shù)字信號(hào),送入計(jì)算機(jī)內(nèi)存;4鍵盤

輸入,這里,我們只討論鍵盤輸入的情況,其他的可以參考有關(guān)資料.

-一般高級(jí)語(yǔ)言的數(shù)據(jù)輸入輸出多有相應(yīng)的語(yǔ)句或函數(shù)倆處理,而匯編語(yǔ)言無(wú)法用

一條指令解決問(wèn)題,他通過(guò)調(diào)用系統(tǒng)功能來(lái)完成這個(gè)任務(wù).調(diào)用系統(tǒng)功能猶如高

級(jí)語(yǔ)言中調(diào)用子程序,它需要先提供實(shí)際參數(shù)(又稱入口參數(shù))以及所調(diào)用的功

能號(hào).調(diào)用結(jié)果返回結(jié)果,即可得到出口參數(shù).

3.4.1輸入字符串

從鍵盤上輸入字符串,可以得到一串字符的ASCII.如果是數(shù)字符,通過(guò)變換和組

合,就可以得到數(shù)據(jù).

輸入字符串,通過(guò)調(diào)用dos功能的Oah號(hào)功能來(lái)實(shí)現(xiàn).它需要一個(gè)字符緩沖區(qū),

以便存儲(chǔ)讀入的字符串。緩沖區(qū)的第一個(gè)字節(jié)保存字符去長(zhǎng)度,它由用戶定義時(shí)

給出,不允許超過(guò)此限定數(shù).如果輸入的超過(guò)次數(shù),系統(tǒng)會(huì)拒絕接受,發(fā)出“嘟

嘟”聲,光標(biāo)也不再向右移動(dòng).

緩沖區(qū)的第二個(gè)字節(jié)是實(shí)際鍵入字符的個(gè)數(shù),鍵入完成后,系統(tǒng)程序會(huì)在那個(gè)單

元自動(dòng)填入鍵入字符的個(gè)數(shù),它不是由用戶確定的,它也不包括最后結(jié)束字符串

輸入的回車字符,雖然此回車符還占用字符區(qū)的一個(gè)字節(jié).

緩沖區(qū)的的三個(gè)字節(jié)起,便是存放字符串的字符區(qū),它按字存放.例如.在數(shù)據(jù)區(qū)

定義了一個(gè)緩沖區(qū)BUFFER,字符區(qū)長(zhǎng)度為20,可表示如下:

BUFFERDB20

REALENDB?

STRUNGDB20DUP(?)

調(diào)用A號(hào)功能的程序段如下:

LEADX,BUFFER;緩沖區(qū)首地址一WX

MOVAH,OAH;調(diào)用功能--aAH

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

假如程序執(zhí)行時(shí),鍵入字符

Thisisastring

那么,緩沖區(qū)BUFFER中各存儲(chǔ)單元的內(nèi)容如下所示:

其中第一個(gè)單元的14H是字符區(qū)長(zhǎng)度,第二個(gè)單元的10H是實(shí)際鍵入字符的個(gè)數(shù),

字符區(qū)中是鍵入字符的ASCII串。ODH為回車符。

例從鍵盤上輸入一個(gè)字符串,并在串尾處加上字符串結(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)存中的字符傳送到顯示器顯示,可以通過(guò)調(diào)用DOS功能的9號(hào)功能來(lái)實(shí)現(xiàn)。該

功能要求被現(xiàn)實(shí)的字符串必須是以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號(hào)功能,

顯示他們。

3.5順序程序設(shè)計(jì)

順序城市最常見(jiàn)的,也是最基本的程序設(shè)計(jì)方法。這種程序在計(jì)算機(jī)內(nèi)村種執(zhí)行

時(shí),按照先后次序,逐句順序執(zhí)行。他沒(méi)有分支也沒(méi)有循環(huán),因此也成為線性程

序。下面是一個(gè)例子。

例兩個(gè)64位無(wú)符號(hào)數(shù)相加的程序。

在8086/8088CPU中,數(shù)據(jù)是16位的,他有8位和16位運(yùn)算指令,但是沒(méi)有32

位,64位這種16位以上的運(yùn)算指令。要進(jìn)行64位相加運(yùn)算可以利用16位加法

指令分別相加4次來(lái)實(shí)現(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è)計(jì)

在程序中,除了最基本的順序結(jié)構(gòu)以外,通常還有各種分支,以滿足不同情況作

不同處理的需要。分支結(jié)構(gòu)有兩種形式,一種是引出兩個(gè)分支的,另一種是引出

多個(gè)分支的。前者類似于高級(jí)語(yǔ)言中的IF——THEN--ELSE語(yǔ)句,后者類似于

高級(jí)語(yǔ)言中的CASE語(yǔ)句,分若嘎呢請(qǐng)昂,進(jìn)行不同的處理。程序在某種條件下

運(yùn)行時(shí),執(zhí)行其中一個(gè)分支。分支結(jié)構(gòu)如圖3—4所示。上述兩種結(jié)構(gòu)分別舉例

如下:

例從鍵盤上輸入兩個(gè)整數(shù),并求其和。

通過(guò)調(diào)用DOS功能,從鍵盤上輸入整數(shù)該數(shù)是以ASCII碼的形式存在內(nèi)存中的。

因此,需要把它轉(zhuǎn)化成二進(jìn)制數(shù),在進(jìn)行加法運(yùn)算。如果計(jì)算機(jī)以一個(gè)字來(lái)表示

一個(gè)整數(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è)計(jì)發(fā)方法又稱為跳轉(zhuǎn)表法,在程序

設(shè)計(jì)中常見(jiàn)到,很有用。例如,以惡程序分成若干個(gè)功能塊,每個(gè)功能塊實(shí)現(xiàn)不

同的功能可以當(dāng)作一個(gè)分支程序,根據(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

這個(gè)程序中,分支標(biāo)的首地址在中BX中,BX作為分支表的指針,分支號(hào)在CL

中隨著分支號(hào)的增加,BX的內(nèi)容也發(fā)生變化,紙箱下一個(gè)分支的地址,因此當(dāng)

AL中的內(nèi)容與CL的內(nèi)容相等時(shí),程序控制就轉(zhuǎn)到BX所致的那個(gè)分支去,從哪

兒在繼續(xù)執(zhí)行。各個(gè)分支執(zhí)行完后,轉(zhuǎn)向何處,可以有變成者根據(jù)需要來(lái)確定。

比如,讓此程序中的各個(gè)分支轉(zhuǎn)向CONTINUE,然后在結(jié)束。

3.7循環(huán)程序設(shè)計(jì)

循環(huán)程序也是程序的一種基本結(jié)構(gòu)。程序中,往往有的程序段需要重復(fù)執(zhí)行多次,

以實(shí)現(xiàn)某種功能,這樣,可以大大簡(jiǎn)化程序設(shè)計(jì)。循環(huán)程序通常有以下三部分組

成:

1.循環(huán)初始狀態(tài)循環(huán)過(guò)程中的工作單元,在循環(huán)開(kāi)始前,往往要給他們賦初

值,以保證循環(huán)能正常地進(jì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)的工作部分是實(shí)現(xiàn)程序功能的程序段,它

是循環(huán)的主要部分。循環(huán)的修改部分是修改部分是修改參加循環(huán)的信息的程序

段,循環(huán)每次執(zhí)行時(shí),有關(guān)信息能發(fā)生信息的相應(yīng)變化,確保循環(huán)程序正常循環(huán)。

3.循環(huán)控制循環(huán)能正常進(jìn)行和結(jié)束,循環(huán)控制是關(guān)鍵。循環(huán)控制條件不合理,

循環(huán)就無(wú)法按正常的預(yù)定進(jìn)行,甚至導(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ù)控制條件進(jìn)行判斷,

不滿足結(jié)束條件則繼續(xù)循環(huán)操作,滿足條件則退出循環(huán)。這一循環(huán)類似高級(jí)語(yǔ)言

中的repeat-until結(jié)構(gòu)。另一類類似while-do結(jié)構(gòu),先檢查是否滿足控制條件,

滿足循環(huán)條件就執(zhí)行循環(huán)體,否則就退出循環(huán)。這兩循環(huán)結(jié)構(gòu)如圖3-7所示。

下面舉例說(shuō)明。

例在一串?dāng)?shù)中找出其中的最大值和最小值,放在指定的存儲(chǔ)單元中。

尋找最大數(shù)和最小數(shù),可以用逐個(gè)比較來(lái)發(fā)現(xiàn),這就需要循環(huán)體來(lái)執(zhí)行,這一串

數(shù)的個(gè)數(shù)是確定的,很能夠想到以他作為循環(huán)控制條件。程序的流程圖如3-8。

通過(guò)這個(gè)程序,讀者不難確定這些數(shù)的類型和位數(shù)。

循環(huán)可以嵌套,形成多重循環(huán)結(jié)構(gòu)。多重循環(huán)程序設(shè)計(jì)的方法與單循環(huán)程序設(shè)計(jì)

大致相同。另外應(yīng)該注意的是各種循環(huán)的控制條件及循環(huán)主體不能混淆,交錯(cuò),

要層次分明。例如從外層循環(huán)進(jìn)入內(nèi)層循環(huán)時(shí),等于重新開(kāi)始一次新的內(nèi)循環(huán),

初始條件等內(nèi)循環(huán)參數(shù)必須重新的設(shè)置。下面,就我們以典型的起泡法分類排序

作為一個(gè)例子,加以說(shuō)明。

例有一個(gè)n個(gè)子的數(shù)組,要求變成使該數(shù)組的元素按從大到小的次序排列。

起泡算法是這樣實(shí)現(xiàn)排序的:從第一個(gè)數(shù)開(kāi)始,依次對(duì)相鄰兩個(gè)數(shù)輛輛進(jìn)行比較,

如果大小次序不對(duì),則是這兩個(gè)數(shù)交換為止,反之,則不交換。這樣這樣進(jìn)行了

第一遍比計(jì)較,最小的數(shù)被置于隊(duì)尾。進(jìn)行第二遍比較時(shí),只需進(jìn)行n-2次第三

遍比較,最多比較到nT遍就可以實(shí)現(xiàn)程序。

圖3-9是起泡算法的一個(gè)示例,圖3-10是其流程圖。

起泡排序的內(nèi)外循環(huán)次數(shù)是已知的外循環(huán)次數(shù)是確定的,為數(shù)組長(zhǎng)度減1,既

(n-1),

內(nèi)循環(huán)的次數(shù)安每次減1的的規(guī)律在變化。這種排序算法不管原來(lái)排序情況如

何,只要進(jìn)行nT次比較,總可以達(dá)到排序的目的。但實(shí)際上,常常不需要比較

n-1次就可以完成排序。因此對(duì)算法可以進(jìn)行改進(jìn),一旦完成排序,就不再進(jìn)行

比較。這里設(shè)立一個(gè)標(biāo)志位,如果進(jìn)行了比較,就該將該標(biāo)志位置1,如果進(jìn)行

一邊比較后,沒(méi)有交換,即該標(biāo)志位仍為零,說(shuō)明排序已經(jīng)完成,程序可以結(jié)束。

該今后的程序如下:

3.8字程序設(shè)計(jì)

解決實(shí)際問(wèn)題時(shí),變成通常都采用模塊化程序設(shè)計(jì)方法。這種方法把一個(gè)程序分

成多個(gè)具有任務(wù)的程序模塊,程序模塊進(jìn)一步分成獨(dú)立的子模塊,分別編成,調(diào)

試,然后連接在一起,形成一個(gè)完整的程序。模塊化設(shè)計(jì)的程序易于編程,調(diào)試,

修改,程序易讀性強(qiáng)。而子程序結(jié)構(gòu)是模塊化的程序設(shè)計(jì)的重要工具。

子程序在匯編語(yǔ)言中又稱為過(guò)程,它相當(dāng)于高級(jí)語(yǔ)言的過(guò)程,函數(shù)或子程序。

它具有獨(dú)立的功能,在程序需要的地方可以調(diào)用它。

子程序使用時(shí);要注意寄存器內(nèi)容的保護(hù)。由于CPU的寄存器的數(shù)量有限,子程

序使用的寄存器往往會(huì)和調(diào)用程序所用得寄存器發(fā)生沖突,破壞了調(diào)用程序中寄

存器的內(nèi)容影響從寄存器返回后的繼續(xù)處理。為了避免這種現(xiàn)象的發(fā)生,應(yīng)當(dāng)在

子程序入口八所用寄存器的內(nèi)容推入堆棧,保存起來(lái),而在退出子程序前恢復(fù)寄

存器的內(nèi)容。

子程序使用中,要解決的一個(gè)重要問(wèn)題是參數(shù)傳頌。在調(diào)用子程序時(shí),經(jīng)常要把

參數(shù)傳送給子程序,子程序在運(yùn)行以后,也常常要送回一些信息給調(diào)用程序,

報(bào)告子程序運(yùn)行狀態(tài)及結(jié)果等等。這種調(diào)用程序和子程序之間的信息傳送,成

為參數(shù)傳頌,也稱為變量傳送或者過(guò)程通信。

參數(shù)傳送可以通過(guò)以下幾種渠道進(jìn)行:寄存器,變量,地指表,堆棧等,下面分

別舉例說(shuō)明。

3.8.1寄存器傳送參數(shù)

例把十進(jìn)制ASCII字符轉(zhuǎn)換為壓縮的BCD碼數(shù)。

通常,從鍵盤上輸入的十進(jìn)制數(shù)字是ASCH字符,每個(gè)數(shù)值以逗號(hào)或分號(hào)間隔,

最后一回車結(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符通過(guò)AX寄存器傳到子程序中,子程序完成

轉(zhuǎn)換后,結(jié)果存在寄存器AH中,參數(shù)結(jié)果又通過(guò)寄存器返回主程序,在傳送參

數(shù)少的時(shí)候,利用寄存器完成參數(shù)傳送是最方便,最快捷的。

3.8.2利用變量傳送參數(shù)

例確定字符串長(zhǎng)度,并顯示長(zhǎng)度值。

字符串的長(zhǎng)度不同于常用的整數(shù),系統(tǒng)并不規(guī)定于一個(gè)定值,在對(duì)字符串進(jìn)行操

時(shí),往往需要確定它的長(zhǎng)度。字符串常常以回車符CR或者美元符$作為結(jié)束標(biāo)志,

因此,

從頭開(kāi)始搜索字符串的結(jié)束標(biāo)志,統(tǒng)計(jì)搜索字符的個(gè)數(shù),便可以得到串長(zhǎng)。

這里,假定串長(zhǎng)最大不超過(guò)255。如果找不到串結(jié)束標(biāo)志,以至串長(zhǎng)超過(guò)255,

程序

不再繼續(xù)搜索,而給出提示信息。正常時(shí),通過(guò)DOS功能調(diào)用,顯示串長(zhǎng)度。圖

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;確定字符串長(zhǎng)度

MOVDX,LENGTH1

CMPDX,1OOH

JBNEXT1;如(DX)<1OOH,

;轉(zhuǎn)去EXT1

LEADX,MESSAGE;如(DX)>=100H,顯示提示信息

MOVAH,9

INT21H

JMPNEXT2

NEXT1:MOVDH,DL;串長(zhǎng)暫存在DH

MOVCL,4

SHRDL,CL;取串長(zhǎng)高4位

CMPDL,9

JBELP

ADDDL,7

LP:ADDDL,30H;DL中的高4位變?yōu)锳SCH

MOVAH,6

INT21H;顯示這個(gè)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;串長(zhǎng)加1

CMPCX,100H

JAEDONE;串長(zhǎng)超過(guò)255,則結(jié)束

CMP[DI],AH

JEDONE;遇'$'則結(jié)束

SCASB;搜索回車

JNEAGAIN;沒(méi)找到,返回繼續(xù)

DONE:MOVLENGTH1,CX

RET

STRLENENDP

CODEENDS

ENDBEGIN

這個(gè)程序中,主程序和子程序直接訪問(wèn)模塊中的變量,通過(guò)變量,實(shí)現(xiàn)調(diào)用程序

和子

程序之間的參數(shù)傳送。

3.8.3利用地址表傳送參數(shù)

這種傳送參數(shù)的辦法是建立一張地址表,把要傳給子程序的參數(shù)存放在地址表

中,調(diào)

用程序把地址表的首地址通過(guò)寄存器傳給子程序。子程序從該地址表獲得所需參

數(shù),也把

結(jié)果存入指定的存儲(chǔ)單元。下面是利用這種方法傳送參數(shù)的例子。

例求一個(gè)字符串的ASCII碼的和。

DATASEGMENT

STRINGDB'Thisisastring!),13

LENGTH1DB17

SUMDW?

TABLEDW3DUP(?);保留3個(gè)參數(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ù)地址,從而實(shí)現(xiàn)參數(shù)傳送。請(qǐng)看下面的例子。

例從一個(gè)字符串中刪去一個(gè)字符。

相應(yīng)的程序如下:

DATASEGMENT

STRINGDB'

LENGTH1DW$-STRING

KEYDB'x';這是某個(gè)將從串中刪去的字符

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)用刪一個(gè)字符子程序

MOVAH,4CH

INT21H

MAINENDP

DELCHAPROC

PUSHBP;保存BP

MOVBP,SP;BP指向當(dāng)前棧頂

PUSHSI

PUSHDI

PUSHCX

CLD

MOVSI,[BP+4];得到LENGTH1地址

MOVCX,[SI];得到長(zhǎng)度

MOVDI,[BP+6];得到STRING地址

REPNESCASB;重復(fù)搜索該字符

JNEDONE;沒(méi)找到,退出

MOVSI,[BP+4

溫馨提示

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

評(píng)論

0/150

提交評(píng)論