第04章匯編程序設(shè)計(jì)_第1頁
第04章匯編程序設(shè)計(jì)_第2頁
第04章匯編程序設(shè)計(jì)_第3頁
第04章匯編程序設(shè)計(jì)_第4頁
第04章匯編程序設(shè)計(jì)_第5頁
已閱讀5頁,還剩170頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

會計(jì)學(xué)1第04章匯編程序設(shè)計(jì)按照指令執(zhí)行的順序,程序的結(jié)構(gòu)可以劃分成以下三種。

順序結(jié)構(gòu):程序按照它編寫的順序執(zhí)行,每條指令只執(zhí)行一

次,這樣的程序稱為“順序結(jié)構(gòu)”的程序。

循環(huán)結(jié)構(gòu):一組指令被反復(fù)地執(zhí)行,這樣的程序稱為“循環(huán)結(jié)

構(gòu)”或者“重復(fù)結(jié)構(gòu)”的程序。

選擇結(jié)構(gòu):根據(jù)某個(gè)條件,一部分指令被執(zhí)行,另一部分指

令沒有被執(zhí)行,這樣的程序稱為“選擇結(jié)構(gòu)”或者

“分支結(jié)構(gòu)”的程序。一個(gè)實(shí)際運(yùn)行的程序,常常是由以上三種結(jié)構(gòu)的程序組合而成的,上面的三種結(jié)構(gòu)稱為程序的“基本結(jié)構(gòu)”。使用這三種基本結(jié)構(gòu),可以編寫出任何所需要的程序。第1頁/共175頁4.1選擇結(jié)構(gòu)程序

4.1.1測試和轉(zhuǎn)移控制指令

4.1.2基本選擇結(jié)構(gòu)

4.1.3單分支選擇結(jié)構(gòu)

4.1.4復(fù)合選擇結(jié)構(gòu)

4.1.5多分支選擇結(jié)構(gòu)第2頁/共175頁

4.1.1

測試和轉(zhuǎn)移控制指令1.無條件轉(zhuǎn)移指令2.比較和測試指令3.條件轉(zhuǎn)移指令第3頁/共175頁執(zhí)行JMP指令后,程序轉(zhuǎn)移到新的“目的位置”執(zhí)行。1.無條件轉(zhuǎn)移指令無條件轉(zhuǎn)移指令的一般格式:JMP 目的位置第4頁/共175頁CODE SEGMENT ASSUME CS:CODESTART: MOV DL,20HONE: MOV AH,2 INT 21H ;輸出DL中的字符

INC DL ;修改DL中的字符代碼

JMP ONE ;轉(zhuǎn)移到“ONE”處繼續(xù)執(zhí)行

MOV AX,4C00H INT 21HCODE ENDS END START[例4-1]用JMP指令實(shí)現(xiàn)轉(zhuǎn)移第5頁/共175頁(1)近程無條件轉(zhuǎn)移指令如果轉(zhuǎn)移的目的位置與出發(fā)點(diǎn)在同一個(gè)段里,這樣的轉(zhuǎn)移稱為“近程”轉(zhuǎn)移或者“段內(nèi)”轉(zhuǎn)移。實(shí)現(xiàn)“近程”轉(zhuǎn)移,實(shí)質(zhì)上是把目標(biāo)位置的“偏移地址”置入IP寄存器。按照尋址方式的不同,近程無條件轉(zhuǎn)移指令有三種格式。第6頁/共175頁短轉(zhuǎn)移

如果目的位置離開出發(fā)點(diǎn)很近,可以使用以下格式:

JMP SHORTLABEL

其中“LABEL”是目的位置的標(biāo)號。這種格式產(chǎn)生的機(jī)器指令代碼最短,為2字節(jié)。100H: JMP SHORTTWO

102H: ……

……

10CH: TWO:…… 指令“JMPSHORTTWO”匯編后產(chǎn)生的機(jī)器指令為“EB0A”。

“EB”是這種類型轉(zhuǎn)移指令的“操作碼”,“0A”是目的位置離開出發(fā)點(diǎn)的距離,10CH-102H=0AH。由于用一個(gè)字節(jié)補(bǔ)碼表示目的地址與當(dāng)前地址的距離,所以轉(zhuǎn)移范圍為下一條指令地址-128~+127字節(jié)以內(nèi)。第7頁/共175頁近程直接轉(zhuǎn)移

JMP 目的位置標(biāo)號指令“JMPTWO”匯編后得到的機(jī)器指令代碼為“E9FDEE”。

“E9”為操作碼

“0EEFDH”為位移量,0EEFDH=0F000H-103H。指令“JMPONE”對應(yīng)的機(jī)器指令代碼為“E90011”

“E9”為操作碼

位移量“1100H”,0F003H+1100H=0103H(舍去進(jìn)位)使用近程直接轉(zhuǎn)移指令可以實(shí)現(xiàn)同一個(gè)段內(nèi)64KB范圍的轉(zhuǎn)移。100H: JMP TWO 103H: ONE: …………0F000H: TWO:JMP ONE0F003H: ……第8頁/共175頁近程間接轉(zhuǎn)移 把轉(zhuǎn)移的目的地址事先存放在某個(gè)寄存器或存儲器單元中,通過這個(gè)寄存器或存儲單元實(shí)現(xiàn)轉(zhuǎn)移。JMPCX ;寄存器間接轉(zhuǎn)移,可使用任何一個(gè)通用寄存器JMPWORDPTR[BX]

;存儲器間接轉(zhuǎn)移,目的地址在存儲單元中第9頁/共175頁1)JMPONE ;近程直接轉(zhuǎn)移2)LEADX,ONEJMPDX ;寄存器間接段內(nèi)轉(zhuǎn)移3)LEABX,TARGETJMPWORDPTR[BX] ;存儲器間接段內(nèi)轉(zhuǎn)移4)JMPTARGET ;存儲器間接段內(nèi)轉(zhuǎn)移已在數(shù)據(jù)段定義存儲器單元“TARGET”:

TAEGET DWONE下面四組指令都可以實(shí)現(xiàn)向標(biāo)號“ONE”的轉(zhuǎn)移:第10頁/共175頁遠(yuǎn)程無條件轉(zhuǎn)移指令可以實(shí)現(xiàn)不同的段之間的轉(zhuǎn)移,執(zhí)行該指令時(shí),CPU把目的段的段基址裝入CS,目的位置的段內(nèi)偏移地址裝入IP。有直接尋址和間接尋址兩種格式。遠(yuǎn)程直接轉(zhuǎn)移JMPFARPTR遠(yuǎn)程標(biāo)號指令匯編后,對應(yīng)的機(jī)器指令為5個(gè)字節(jié):

1個(gè)字節(jié)操作碼“0EAH”2個(gè)字節(jié)目的地址的段內(nèi)偏移地址

2個(gè)字節(jié)目的標(biāo)號所在段的段基址(2)遠(yuǎn)程無條件轉(zhuǎn)移指令第11頁/共175頁遠(yuǎn)程間接轉(zhuǎn)移遠(yuǎn)程轉(zhuǎn)移需要32位的目的地址,使用間接轉(zhuǎn)移時(shí),需要把32位目的地址事先裝入用“DD”定義的存儲單元。1)JMPFARPTRTWO ;遠(yuǎn)程直接轉(zhuǎn)移2)LEABX,FAR_TGTJMPDWORDPTR[BX] ;遠(yuǎn)程間接轉(zhuǎn)移3)JMPFAR_TGT ;遠(yuǎn)程間接轉(zhuǎn)移假設(shè)已在數(shù)據(jù)段定義存儲器單元“FAR_TGT”如下:

FAR_TGT DD TWO下面三組指令都可以實(shí)現(xiàn)向遠(yuǎn)程標(biāo)號“TWO”的轉(zhuǎn)移:第12頁/共175頁2.比較和測試指令(1)CMP(Compare,比較)指令指令格式:

CMP 目的操作數(shù),源操作數(shù)目的操作數(shù):8位/16位的寄存器/存儲器操作數(shù)。源操作數(shù):與目的操作數(shù)同類型的寄存器/存儲器/立即數(shù)。功能:目的操作數(shù)-源操作數(shù),保留運(yùn)算產(chǎn)生的標(biāo)志位,不保留

運(yùn)算的差。用來比較兩個(gè)有符號數(shù)或無符號數(shù)的大小。第13頁/共175頁CF=0,目的操作數(shù)≥源操作數(shù)CF=1,目的操作數(shù)<源操作數(shù)對于有符號數(shù):OF=0時(shí),SF為正確的結(jié)果符號

OF=1時(shí),SF與正確的符號位相反

OF⊕SF的運(yùn)算結(jié)果反映了正確的結(jié)果符號OF⊕SF=0,目的操作數(shù)≥源操作數(shù)OF⊕SF=1,目的操作數(shù)<源操作數(shù)對于無符號數(shù):第14頁/共175頁ZF=0 (X)≠5OF=0 減法操作沒有產(chǎn)生溢出,SF是正確的結(jié)果符號位SF=1 如果X中存放的是有符號數(shù),X<5

(由于OF=0,所以符號標(biāo)志SF有效/正確)CF=0 如果X中存放的是無符號數(shù),X>5

(由于ZF=0,所以不相等)假設(shè)存儲器變量(X)=80H,指令“CMPX,5”執(zhí)行后:第15頁/共175頁(2)TEST(Test,測試)指令指令格式:

TEST 目的操作數(shù),源操作數(shù)目的操作數(shù):8位/16位的寄存器/存儲器操作數(shù)。源操作數(shù):與目的操作數(shù)同類型的寄存器/存儲器/立即數(shù)。功能:TEST指令將目的操作數(shù)與源操作數(shù)進(jìn)行邏輯乘運(yùn)算,保

留運(yùn)算產(chǎn)生的各標(biāo)志位,但是不保留邏輯乘的結(jié)果。該

指令用來測試目的操作數(shù)中某幾位二進(jìn)制的特征。第16頁/共175頁如果ZF=0,說明BL寄存器的D2D1≠00,這兩位為01,10或11。如果ZF=1,說明BL寄存器的D2D1=00,這兩位為00。指令TEST VAR,1執(zhí)行后:如果ZF=0,說明變量VAR的D0位為1,該數(shù)為奇數(shù)如果ZF=1,說明變量VAR的D0位為0,該數(shù)為偶數(shù)指令TEST BL,6執(zhí)行后:第17頁/共175頁3.條件轉(zhuǎn)移指令“J”是條件轉(zhuǎn)移指令操作碼的第一個(gè)字母“cc”是代表轉(zhuǎn)移條件的1~3個(gè)字母“l(fā)abel”是轉(zhuǎn)移目的地的標(biāo)號。條件轉(zhuǎn)移指令格式:

Jcc label第18頁/共175頁(1)根據(jù)兩個(gè)有符號數(shù)比較結(jié)果的條件轉(zhuǎn)移指令兩個(gè)有符號數(shù)的比較結(jié)果通過OF,SF,ZF反映出來

G(Greater,大于)L(Less,小于)E(Equal,等于)N(Not,否)例:JG/JNLE 大于(不小于等于)則轉(zhuǎn)移

JNL/JGE不小于(大于或等于)則轉(zhuǎn)移

JE/JZ 等于(為零)則轉(zhuǎn)移第19頁/共175頁指令助記符

指令功能轉(zhuǎn)移條件JG,JNLE大于(不小于等于)時(shí)轉(zhuǎn)移OF⊕SF=0且ZF=0JGE,JNL大于等于(不小于)時(shí)轉(zhuǎn)移OF⊕SF=0JZ,JE為零(相等)時(shí)轉(zhuǎn)移ZF=1JNZ,JNE不為零(不相等)時(shí)轉(zhuǎn)移ZF=0JL,JNGE小于(不大于等于)時(shí)轉(zhuǎn)移OF⊕SF=1JLE,JNG小于等于(不大于)時(shí)轉(zhuǎn)移OF⊕SF=1或ZF=1根據(jù)有符號數(shù)大小的條件轉(zhuǎn)移指令第20頁/共175頁MOV AX,X ;取出X的值送AXCMP AX,Y ;比較兩個(gè)操作數(shù),建立需要的標(biāo)志位JG GREATER ;如果X>Y,轉(zhuǎn)移到“GREATER”處執(zhí)行JE EQUAL ;如果X=Y,轉(zhuǎn)移到“EQUAL”處執(zhí)行LESS: ;否則,執(zhí)行標(biāo)號“LESS”處的指令

……GREATER: ……EQUAL: ……下面程序根據(jù)有符號字變量X和Y的大小決定程序的走向。第21頁/共175頁

SUB AX,BX ;AX←(AX)-(BX),建立標(biāo)志位

JGE SKIP ;如果(AX)≥0,轉(zhuǎn)標(biāo)號“SKIP” NEG AX ;如果(AX)<0,把AX的值取反SKIP:

JGGREATER ;如果X>Y,轉(zhuǎn)移到“GREATER”處

JEEQUAL ;如果X=Y,轉(zhuǎn)移到“EQUAL”處

JLLESS ;如果X<Y,轉(zhuǎn)移到“LESS”處LESS: ……下面程序能夠正確運(yùn)行,但最后一條指令有“畫蛇添足”之嫌。下面的程序計(jì)算AX=|AX-BX|第22頁/共175頁(2)根據(jù)兩個(gè)無符號數(shù)比較結(jié)果的條件轉(zhuǎn)移指令 兩個(gè)有符號數(shù)的比較結(jié)果通過CF,ZF反映出來,代表轉(zhuǎn)移條件的字母:

A(Above,高于)

B(Below,低于)

E(Equal,等于)第23頁/共175頁指令助記符指令功能轉(zhuǎn)移條件JA,JNBE高于(不低于等于)時(shí)轉(zhuǎn)移CF=0且ZF=0JAE,JNB,JNC高于等于(不低于)時(shí)轉(zhuǎn)移CF=0JZ,JE為零(相等)時(shí)轉(zhuǎn)移ZF=1JNZ,JNE不為零(不相等)時(shí)轉(zhuǎn)移ZF=0JB,JNAE,JC低于(不高于等于)時(shí)轉(zhuǎn)移CF=1JBE,JNA低于等于(不高于)時(shí)轉(zhuǎn)移CF=1或ZF=1根據(jù)無符號數(shù)大小的條件轉(zhuǎn)移指令第24頁/共175頁(3)根據(jù)單個(gè)標(biāo)志位的條件轉(zhuǎn)移指令指令操作碼助記符指令功能轉(zhuǎn)移條件JC,JB,JNAE有進(jìn)位時(shí)轉(zhuǎn)移CF=1JNC,JNB,JAE無進(jìn)位時(shí)轉(zhuǎn)移CF=0JZ,JE為零(相等)時(shí)轉(zhuǎn)移ZF=1JNZ,JNE不為零(不相等)時(shí)轉(zhuǎn)移ZF=0JS為負(fù)時(shí)轉(zhuǎn)移SF=1JNS為正時(shí)轉(zhuǎn)移SF=0JO溢出時(shí)轉(zhuǎn)移OF=1JNO不溢出時(shí)轉(zhuǎn)移OF=0JP,JPE“1”的個(gè)數(shù)為偶數(shù)時(shí)轉(zhuǎn)移PF=1JNP,JPO“1”的個(gè)數(shù)為奇數(shù)時(shí)轉(zhuǎn)移PF=0第25頁/共175頁

JNG Skip JMP LabelSkip: …… 對于16位8086CPU,條件轉(zhuǎn)移指令的轉(zhuǎn)移范圍在下一條指令地址-128~+127字節(jié)之間。如果轉(zhuǎn)移目的位置超出了上述范圍,匯編時(shí)將報(bào)告錯(cuò)誤。

JG Label;如果標(biāo)號“Label”超出范圍,匯編時(shí)將出錯(cuò)可以把上面指令修改為:第26頁/共175頁(4)根據(jù)CX/ECX寄存器值的條件轉(zhuǎn)移指令指令格式:

JCXZ Label ;若CX=0,轉(zhuǎn)移到LabelJECXZ Label ;若ECX=0,轉(zhuǎn)移到Label它們的轉(zhuǎn)移范圍固定為下一條指令地址-128~+127字節(jié)以內(nèi)。第27頁/共175頁為“|X|>3”和“|X|≤3”分別編制了進(jìn)行不同處理的指令序列。 如果條件“|X|≤3”成立(為“真”),執(zhí)行“Y=3X-5”

如果條件“|X|≤3”不成立(為“假”),執(zhí)行Y=6

通過在不同的程序之間進(jìn)行選擇,實(shí)現(xiàn)程序的不同功能,

“選擇結(jié)構(gòu)”因此得名。計(jì)算分段函數(shù)的值4.1.2

基本選擇結(jié)構(gòu)第28頁/共175頁第29頁/共175頁[例4-2]計(jì)算分段函數(shù)INCLUDE YLIB.HDATA SEGMENTPROMPT DB 0DH,0AH,“InputX(-10000~+10000):$”X DW ?OUT_MSG DB 0DH,0AH,“Y=$”DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATASTART: MOV AX,DATA MOV DS,AX ;裝載DS第30頁/共175頁

LEA DX,PROMPT ;輸入提示信息

CALL READINT ;從鍵盤上輸入X的值

MOV X,AX ;保存輸入值COMP: CMP X,3 ;比較,X>3? JG GREATER ;X>3成立,轉(zhuǎn)“GREATER” CMP X,-3 ;比較,X<-3? JL GREATER ;X<-3成立,轉(zhuǎn)“GREATER”LESS: ;|X|≤3的程序段

MOV BX,AX ;BX←X SAL AX,1 ;AX←2X ADD AX,BX ;AX←2X+X SUB AX,5 ;AX←3X-5 JMP OUTPUT第31頁/共175頁GREATER: MOV AX,6 ;|X|>3的程序段OUTPUT: LEA DX,OUT_MSG ;結(jié)果的前導(dǎo)文字

CALL WRITEINT ;輸出計(jì)算結(jié)果

CALL CRLF ;輸出回車換行EXIT: MOV AX,4C00H INT 21HCODE ENDS END START第32頁/共175頁復(fù)合邏輯表達(dá)式的分解第33頁/共175頁4.1.3

單分支選擇結(jié)構(gòu)如果選擇結(jié)構(gòu)的一個(gè)分支為“空”,這樣的程序流程稱為

“單分支選擇結(jié)構(gòu)”。合理地選擇Jcc指令所使用的條件,可以使程序更加流暢??梢园岩恍┗具x擇結(jié)構(gòu)程序改寫為單分支選擇結(jié)構(gòu)。第34頁/共175頁計(jì)算AX←|AX|的兩種判斷方法:第35頁/共175頁[例4-3]將4位二進(jìn)制轉(zhuǎn)換成對應(yīng)的十六進(jìn)制字符

MOV AL,X CMP AL,9 JA ALPH ADD AL,30H JMP DONEALPH: ADD AL,37HDONE: MOV Y,AL

MOV AL,X OR AL,30H CMP AL,‘9’ JBE DONE ADD AL,7DONE: MOV Y,AL第36頁/共175頁 選擇結(jié)構(gòu)一個(gè)分支的程序中又出現(xiàn)了選擇結(jié)構(gòu),這樣的

結(jié)構(gòu)稱為“復(fù)合選擇結(jié)構(gòu)”或者“嵌套選擇結(jié)構(gòu)”。

4.1.4

復(fù)合選擇結(jié)構(gòu)排除法:每次判斷排除若干可能,留下一種可能情況進(jìn)行處理;確認(rèn)法:每次判斷確認(rèn)一種可能,對已確認(rèn)的情況進(jìn)行處理。第37頁/共175頁;方法a,逐項(xiàng)排除

CMP X,0JGE UN_MINUSMINUS:MOV Y,-1JMP DONEUN_MINUS:JE ZEROMOV Y,1JMP DONEZERO: MOV Y,0DONE: ……;方法b,逐項(xiàng)確認(rèn)

CMP X,0JG PLUSJE ZEROMINUS:MOV Y,-1JMP DONEPLUS:MOV Y,1JMP DONEZERO:MOV Y,0DONE: ……[例4-4]計(jì)算Y=SGN(X)第38頁/共175頁復(fù)合分支選擇結(jié)構(gòu)第39頁/共175頁4.1.5

多分支選擇結(jié)構(gòu)在選擇結(jié)構(gòu)程序里,如果可供選擇的程序塊多于兩個(gè),這樣的結(jié)構(gòu)稱為多分支選擇結(jié)構(gòu),如下圖(a)所示,下圖(b)是匯編語言程序的實(shí)現(xiàn)方法。第40頁/共175頁DATA SEGMENTPROMPT DB 0DH,0AH,“Inputanumber(1~3):$”MSG1 DB 0DH,0AH,“FUNCTION1EXECUTED.$”MSG2 DB 0DH,0AH,“FUNCTION2EXECUTED.$”MSG3 DB 0DH,0AH,“FUNCTION3EXECUTED.$”DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATASTART: MOV AX,DATA MOV DS,AX[例4-5]從鍵盤上輸入數(shù)字“1”到“3”,根據(jù)輸入選擇對應(yīng)程序塊執(zhí)行。第41頁/共175頁INPUT: LEA DX,PROMPT MOV AH,9 INT 21H ;輸出提示信息

MOV AH,1 INT 21H ;輸入一個(gè)數(shù)字

CMP AL,‘1’ JB INPUT ;“0”或非數(shù)字,重新輸入

JE F1 ;數(shù)字“1”,轉(zhuǎn)F1 CMP AL,‘2’ JE F2 ;數(shù)字“2”,轉(zhuǎn)F2 CMP AL,‘3’ JE F3 ;數(shù)字“3”,轉(zhuǎn)F3 JMP INPUT ;大于“3”,重新輸入第42頁/共175頁F1: LEA DX,MSG1 ;F1程序塊

JMP OUTPUTF2: LEA DX,MSG2 ;F2程序塊

JMP OUTPUTF3: LEA DX,MSG3 ;F3程序塊

JMP OUTPUTOUTPUT: MOV AH,9 INT 21H MOV AX,4C00H INT 21HCODE ENDS END START第43頁/共175頁把完成各功能的程序塊入口地址放在一張表格中,根據(jù)輸入,計(jì)算出該功能程序塊入口地址在表中的位置,通過存儲器間接轉(zhuǎn)移轉(zhuǎn)入對應(yīng)位置執(zhí)行。DATA SEGMENTPROMPT DB0DH,0AH,“Inputanumber(1~3):$”MSG1 DB0DH,0AH,“FUNCTION1EXECUTED.$”MSG2 DB0DH,0AH,“FUNCTION2EXECUTED.$”MSG3 DB0DH,0AH,“FUNCTION3EXECUTED.$”ADDTBL DWF1,F2,F3DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA第44頁/共175頁START:MOVAX,DATA MOV DS,AXINPUT:LEA DX,PROMPT MOV AH,9 INT 21H ;顯示提示信息

MOV AH,1 INT 21H ;輸入一個(gè)數(shù)字

CMP AL,‘1’ JB INPUT ;不正確輸入,重新輸入

CMP AL,‘3’ JA INPUT ;不正確輸入,重新輸入第45頁/共175頁

SUB AL,‘1’ ;將數(shù)字字符“1”到“3”轉(zhuǎn)換為0,1,2 SHL AL,1 ;轉(zhuǎn)換為0,2,4 MOV BL,AL MOV BH,0 ;轉(zhuǎn)入BX JMP ADDTBL[BX] ;間接尋址,轉(zhuǎn)移到對應(yīng)程序塊F1: LEA DX,MSG1 ;F1程序塊

JMP OUTPUT F2: LEA DX,MSG2 ;F2程序塊

JMP OUTPUTF3: LEA DX,MSG3 ;F3程序塊

JMP OUTPUT ;這條指令可以省略第46頁/共175頁OUTPUT: MOV AH,9 INT 21H MOV AX,4C00H INT 21HCODE ENDS END START第47頁/共175頁4.2循環(huán)結(jié)構(gòu)程序

4.2.1循環(huán)指令

4.2.2計(jì)數(shù)循環(huán)

4.2.3條件循環(huán)

4.2.4多重循環(huán)第48頁/共175頁 循環(huán)結(jié)構(gòu)也稱為“重復(fù)結(jié)構(gòu)”,它使得一組指令重復(fù)地執(zhí)行,可以用有限長度的程序完成大量的處理任務(wù),幾乎所有的應(yīng)用程序中都離不開循環(huán)結(jié)構(gòu)。第49頁/共175頁計(jì)數(shù)循環(huán):循環(huán)的次數(shù)事先已經(jīng)知道,用一個(gè)變量(寄存器

或存儲器單元)記錄循環(huán)的次數(shù)(稱為“循環(huán)計(jì)數(shù)

器”)。進(jìn)行減法計(jì)數(shù)時(shí),循環(huán)計(jì)數(shù)器的初值直接設(shè)為

循環(huán)次數(shù),每循環(huán)一次將計(jì)數(shù)器減1,計(jì)數(shù)器減為0時(shí),

循環(huán)結(jié)束。條件循環(huán):循環(huán)的次數(shù)事先并不確定,每次循環(huán)開始時(shí)或結(jié)

束后測試某個(gè)條件,根據(jù)這個(gè)條件是否滿足來決定是

否繼續(xù)下一次循環(huán)。按照循環(huán)結(jié)束的條件,有以下兩類循環(huán):第50頁/共175頁按照循環(huán)結(jié)束判斷在循環(huán)中的位置,有以下兩種結(jié)構(gòu)的循環(huán):WHILE循環(huán):進(jìn)入循環(huán)后,先判斷循環(huán)結(jié)束條件,條件滿足

則退出循環(huán),循環(huán)次數(shù)最少為0次。DO-WHILE循環(huán):進(jìn)入循環(huán)后,先執(zhí)行工作部分,然后判斷循環(huán)

繼續(xù)的條件,條件滿足則轉(zhuǎn)向工作部分繼續(xù)循環(huán),循環(huán)

次數(shù)最少1次。第51頁/共175頁第52頁/共175頁 循環(huán)一般由以下4個(gè)部分組成:(1)初始化部分:為循環(huán)做準(zhǔn)備,如累加器清零,設(shè)置地址指

針和計(jì)數(shù)器的初始值等。(2)工作部分:實(shí)現(xiàn)循環(huán)的基本操作,也就是需要重復(fù)執(zhí)行的

一段程序。(3)修改部分:修改指針的值,為下一次循環(huán)做準(zhǔn)備。(4)控制部分:修改計(jì)數(shù)器的值,判斷循環(huán)條件,結(jié)束循環(huán)或繼續(xù)循環(huán)。第53頁/共175頁LOOP Label ;CX←CX-1,若(CX)≠0,轉(zhuǎn)移到LabelLOOPZ/LOOPELabel

;CX←CX-1,若(CX)≠0且ZF=1,轉(zhuǎn)移到LabelLOOPNZ/LOOPNELabel

;CX←CX-1,若(CX)≠0且ZF=0,轉(zhuǎn)移到Label4.2.1

循環(huán)指令 循環(huán)指令采用相對尋址方式,Label距離循環(huán)指令的下一條

指令必須在-128~+127B之內(nèi)。第54頁/共175頁

LOOPZ/LOOPE,LOOPNZ/LOOPNE指令的功能也可以由

Jcc指令實(shí)現(xiàn)。由于對CX先減1,后判斷,如果CX的初值為0,將循環(huán)

65536次。循環(huán)指令的執(zhí)行不影響標(biāo)志位。LOOP指令的功能可以用Jcc指令實(shí)現(xiàn):DEC CX ;CX←CX-1JNZ Label ;若(CX)≠0(也就是ZF=0),轉(zhuǎn)移到Label第55頁/共175頁計(jì)數(shù)循環(huán)是基本的循環(huán)組織方式,用循環(huán)計(jì)數(shù)器的值來控制循環(huán),有時(shí)候也可以結(jié)合其它條件共同控制。4.2.2

計(jì)數(shù)循環(huán)[例4-6]從鍵盤上輸入一個(gè)字符串(不超過80個(gè)字符),將它

逆序后輸出。INCLUDE YLIB.HDATA SEGMENTBUFFER DB 81,?,81DUP(?)MESS DB 0AH,0DH,“Inputastringplease:$”DATA ENDS第56頁/共175頁CODE SEGMENTASSUME CS:CODE,DS:DATASTART:MOV AX,DATA MOV DS,AX LEA DX,MESS MOV AH,09H INT 21H ;輸出提示信息

MOV AH,0AH LEA DX,BUFFER INT 21H ;輸入字符串

CALL CRLF LEA BX,BUFFER ;緩沖區(qū)首地址送BX MOV CL,BUFFER+1 MOV CH,0 ;輸入字符個(gè)數(shù)送CX(循環(huán)次數(shù))第57頁/共175頁

ADD BX,CX INC BX ;計(jì)算字符串末地址送BX(指針)DISP: MOV DL,[BX] MOV AH,02H INT 21H ;逆序輸出一個(gè)字符

DEC BX ;修改指針

LOOP DISP ;計(jì)數(shù)循環(huán)

CALL CRLF ;輸出換行、回車,結(jié)束本行

MOV AX,4C00H INT 21HCODE ENDS END START第58頁/共175頁用總分減去最高分、最低分,最后除以5,得到需要的成績。求N個(gè)數(shù)據(jù)中最大值的方法:

預(yù)設(shè)一個(gè)“最大值”,

取出一個(gè)數(shù)據(jù)與這個(gè)“最大值”進(jìn)行比較,

如果數(shù)據(jù)大于“最大值”,則將該數(shù)據(jù)作為新的“最大值”。

進(jìn)行N次比較之后留下的就是這N個(gè)數(shù)據(jù)的最大值。預(yù)設(shè)的“最大值”的初值可以從N個(gè)數(shù)據(jù)中任取一個(gè),也可以根

據(jù)數(shù)據(jù)的范圍,取一個(gè)該范圍內(nèi)的最小的數(shù)。計(jì)算最小值的方法與此類似。[例4-7]從鍵盤上輸入七名裁判的評分(0~10),扣除一個(gè)最

高分,一個(gè)最低分,計(jì)算出其它五項(xiàng)評分的平均值(保留

一位小數(shù)),在顯示器上輸出。第59頁/共175頁INCLUDE YLIB.HDATA SEGMENTMESS1 DB 0DH,0AH,“Inputascore(0~10):$”MESS2 DB 0DH,0AH,“Thefinalscoreis:$”C5 DB 5MAX DB ?MIN DB ?SUM DB ?DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATASTART: MOV AX,DATA MOV DS,AX第60頁/共175頁

MOV SUM,0 ;累加器清零

MOV MAX,0 ;“最大值”預(yù)設(shè)為0 MOV MIN,255 ;“最小值”預(yù)設(shè)為255 MOV CX,7 ;循環(huán)計(jì)數(shù)器,初值7ONE: LEA DX,MESS1 CALL READDEC ;鍵盤輸入一個(gè)分?jǐn)?shù)

ADD SUM,AL ;累加

CMP MAX,AL ;與“最大值”比較

JA L1 MOV MAX,AL ;大于“最大值”則保留L1: CMP MIN,AL ;與“最小值”比較

JB L2 MOV MIN,AL ;小于“最小值”則保留L2: LOOP ONE ;計(jì)數(shù)循環(huán)第61頁/共175頁

MOV AL,SUM SUB AL,MAX SUB AL,MIN ;從總分中減去最大、最小值

MOV SUM,AL XOR AH,AH ;高8位清零

DIV C5 ;求平均值

PUSH AX ;保留余數(shù)(在AH中)

MOV AH,0 ;清余數(shù)

LEA DX,MESS2 CALL WRITEDEC ;輸出結(jié)果的整數(shù)部分第62頁/共175頁

MOV DL,‘.’ MOV AH,2 INT 21H ;輸出小數(shù)點(diǎn)

POP AX ;從堆棧彈出余數(shù)

SHL AH,1 ;計(jì)算小數(shù)部分:(AH÷5)×10=AH×2 MOV DL,AH OR DL,30H ;轉(zhuǎn)換成ASCII代碼

MOV AH,2 INT 21H ;輸出結(jié)果的小數(shù)部分

CALL CRLF ;輸出回車換行,結(jié)束本行

MOV AX,4C00H INT 21HCODE ENDS END START第63頁/共175頁4.2.3

條件循環(huán)DATA SEGMENTSTRING DB “Astringfortesting.”,0LENTH DW?DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATASTART:MOV AX,DATA MOV DS,AX[例4-8]字符串STRING以代碼0結(jié)束,求這個(gè)字符串的長度(字符個(gè)數(shù))。第64頁/共175頁

LEA SI,STRING ;裝載字符串指針

MOV CX,0 ;設(shè)置計(jì)數(shù)器初值TST: CMP BYTEPTR[SI],0;比較

JE DONE ;字符串結(jié)束,轉(zhuǎn)向DONE保存結(jié)果

INC SI ;修改指針

INC CX ;計(jì)數(shù)

JMP TST ;轉(zhuǎn)向TST,繼續(xù)循環(huán)DONE: MOV LENTH,CX ;保存結(jié)果

MOV AX,4C00H INT 21HCODE ENDS END START第65頁/共175頁

……TST: CMP BYTEPTR[SI],0 ;比較

INC SI ;修改指針

INC CX ;計(jì)數(shù)

JNE TST ;轉(zhuǎn)向TST,繼續(xù)循環(huán)

……錯(cuò)在哪里?運(yùn)行結(jié)果會怎樣?第66頁/共175頁DATA SEGMENTPOSITION DW ?STRING DB “Thisisastringforexample.”,0DATA ENDSCODE SEGMENTASSUME DS:DATA,CS:CODESTART: MOV AX,DATA MOV DS,AX[例4-9]查找字母’a’在字符串STRING中第一次出現(xiàn)的位置,

如果未出現(xiàn),置位置值為-1。第67頁/共175頁

MOV SI,-1 ;SI用作字符串字符指針

MOV CX,30 ;字符串長度30L0: INC SI ;修改指針

CMP STRING[SI],‘a(chǎn)’ ;一個(gè)字符與’a’進(jìn)行比較

LOOPNE L0 ;字符串未結(jié)束,未找到,繼續(xù)

JNE NOTFOUND ;未找到,轉(zhuǎn)“NOTFOUND” MOV POSITION,SI ;保存位置值

JMP EXITNOTFOUND:MOV POSITION,-1 ;未找到,置位置值為-1EXIT: MOV AX,4C00H INT 21HCODE ENDS END START第68頁/共175頁字符串內(nèi)找到字符’a’:循環(huán)結(jié)束時(shí)ZF=1,SI內(nèi)是字符的出

現(xiàn)位置(從0開始);字符串內(nèi)未找到字符’a’:循環(huán)結(jié)束時(shí)ZF=0,SI內(nèi)是字符串

的長度-1(30-1=29)。程序使用LOOPNE指令來控制循環(huán),既有計(jì)數(shù)控制,又有條件控制。循環(huán)結(jié)束有兩種可能性:對于LOOPZ/LOOPE,LOOPNZ/LOOPNE控制的循環(huán),一般應(yīng)在循環(huán)結(jié)束后用條件轉(zhuǎn)移指令分開這兩種情況,分別處理。第69頁/共175頁4.2.4

多重循環(huán)如果一個(gè)循環(huán)的循環(huán)體內(nèi)包含了另一個(gè)循環(huán),稱這個(gè)循環(huán)為“多重循環(huán)”,各層循環(huán)可以是計(jì)數(shù)循環(huán)或者條件循環(huán)。第70頁/共175頁[例4-10]打印20H~7FH之間的ASCII字符表。

!“#$%&‘()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghIjklmnopqrstuvwxyz{|}~

第71頁/共175頁打印格式:每行16個(gè)字符,共6行。打印1行:打印1個(gè)字符的過程重復(fù)16次,構(gòu)成一個(gè)計(jì)數(shù)循環(huán)(內(nèi)循環(huán))。打印6行:打印1行字符的過程重復(fù)6次,構(gòu)成另一個(gè)計(jì)數(shù)循環(huán)(外循環(huán))。第72頁/共175頁INCLUDE YLIB.HCODE SEGMENTASSUME CS:CODE,DS:CODESTART: MOV BL,20H ;第一個(gè)字符的ASCII代碼

MOV CH,6 ;行數(shù)計(jì)數(shù)器初值;============打印一行循環(huán)開始=============L0: CALL CRLF ;開始一個(gè)新行

MOV CL,16 ;列計(jì)數(shù)器初值第73頁/共175頁;-------------------打印一個(gè)字符的循環(huán)開始---------------------L1: MOV DL,BL ;裝入一個(gè)字符ASCII代碼

MOV AH,2 INT 21H ;輸出一個(gè)字符

MOV DL,20H MOV AH,2 INT 21H ;輸出一個(gè)空格

INC BL ;準(zhǔn)備下一個(gè)待輸出的ASCII碼

DEC CL ;列數(shù)計(jì)數(shù)L11: JNZ L1 ;列數(shù)未滿(本行未完),轉(zhuǎn)L1繼續(xù);---------------------打印一個(gè)字符的循環(huán)結(jié)束----------------------第74頁/共175頁

DEC CH ;行數(shù)計(jì)數(shù)L00: JNZ L0 ;行數(shù)未滿,轉(zhuǎn)L0繼續(xù);=============打印一行的循環(huán)結(jié)束============ CALL CRLF ;結(jié)束最后一行

MOV AX,4C00H INT 21HCODE ENDS END START第75頁/共175頁

…… MOV BL,20H ;第一個(gè)字符的ASCII代碼

MOV CX,6 ;行數(shù)計(jì)數(shù)器初值 ;=============打印一行循環(huán)開始==============L0: CALL CRLF ;開始一個(gè)新行

PUSH CX ;保存CX中的行計(jì)數(shù)器值

MOV CX,16 ;CX中置入列計(jì)數(shù)器初值借助于堆棧,將CX“分身”為兩個(gè)計(jì)數(shù)器第76頁/共175頁;--------------------打印一個(gè)字符的循環(huán)開始--------------------L1: MOV DL,BL ;裝入一個(gè)字符ASCII代碼

…… ……L11: LOOP L1 ;列數(shù)未滿(本行未完),轉(zhuǎn)L1繼續(xù);-------------------打印一個(gè)字符的循環(huán)結(jié)束----------------------- POP CX ;恢復(fù)CX為行計(jì)數(shù)器L00: LOOP L0 ;行數(shù)計(jì)數(shù),行數(shù)未滿,轉(zhuǎn)L0繼續(xù);==============打印一行的循環(huán)結(jié)束============== ……第77頁/共175頁4.3字符串處理

4.3.1與無條件重復(fù)前綴配合使用的字符串處理指令

4.3.2與有條件重復(fù)前綴配合使用的字符串處理指令

第78頁/共175頁字符串:計(jì)算機(jī)中常常用到字符串,如變量名、文件名等都是字符串,每個(gè)字符的編碼占用一個(gè)字節(jié),連續(xù)地存存貯在內(nèi)存儲器中。文件:文件是存放在外存儲器上的程序或數(shù)據(jù)。第79頁/共175頁串操作指令的共同特點(diǎn):源操作數(shù)由DS:[SI]提供(有時(shí)也可以由AL、AX、EAX提供)目的操作數(shù)由ES:[DI]提供每執(zhí)行一次串操作,自動修改SI和(或)DI,使其指向下一個(gè)字節(jié)、字或雙字方向標(biāo)志DF控制對SI、DI遞增或是遞減指令STD將DF置1,指令CLD將DF清0第80頁/共175頁(1)MOVS字符串傳送指令格式:MOVSB/MOVSW/MOVSD

執(zhí)行的操作:

目的操作數(shù)單元←源操作數(shù),ES:[DI]←DS:[SI]修改SI和DI值4.3.1

與無條件重復(fù)前綴REP配合使用的串指令第81頁/共175頁(2)REP串重復(fù)操作前綴格式:

REP串操作指令

執(zhí)行的操作:重復(fù)執(zhí)行串操作指令,直到CX的值為零如果(CX)≠0:(CX)=(CX)-1執(zhí)行串指令轉(zhuǎn)向①如果(CX)=0,結(jié)束本指令操作第82頁/共175頁[例4-11]把長度為100的字符串str1復(fù)制到str2開始的存儲單元中假設(shè)已經(jīng)執(zhí)行如下指令,裝載了DS:SI和ES:DI。

MOV AX,SEGstr1 ;源數(shù)據(jù)的段地址送入DS MOV DS,AX LEA SI,str1 ;源數(shù)據(jù)的起始偏移地址送入SI MOV AX,SEGstr2 ;目的數(shù)據(jù)的段地址送入ES MOV ES,AX LEA DI,str2 ;目的數(shù)據(jù)的起始偏移地址送入DI第83頁/共175頁用循環(huán)控制方法編寫的程序

MOV CX,100 ;字符串長度送入CXAGAIN:MOV AL,[SI] ;從源數(shù)據(jù)區(qū)取出一個(gè)字節(jié)

MOV ES:[DI],AL ;存入目的數(shù)據(jù)區(qū)

INC SI ;修改源數(shù)據(jù)區(qū)指針

INC DI ;修改目的數(shù)據(jù)區(qū)指針

LOOP AGAIN ;重復(fù)上面的操作100次第84頁/共175頁用字符串傳送指令編寫的程序

MOV CX,100 ;字符串長度送入CXAGAIN:MOVSB ;從源數(shù)據(jù)傳送一個(gè)字節(jié)到目的數(shù)據(jù)區(qū)

LOOP AGAIN ;重復(fù)上面的操作100次用帶重復(fù)前綴的字符串傳送指令編寫的程序

CLD ;方向標(biāo)志DF清0 MOV CX,100 ;字符串長度送人CX REP MOVSB ;執(zhí)行100次MOVSB指令第85頁/共175頁(3)STOS存字符串指令格式:

STOSB/STOSW/STOSD

執(zhí)行的操作:目的存儲單元←累加器字節(jié)操作:ES:[DI]←(AL)字操作:

ES:[DI]←(AX)雙字操作:ES:[DI]←(EAX)修改DI值第86頁/共175頁(4)

LODS取字符串指令格式:

LODSB/LODSW/LODSD

執(zhí)行的操作:累加器←源存儲單元字節(jié)操作:(AL)

←DS:[SI]

字操作:

(AX)

←DS:[SI]

雙字操作:(EAX)←DS:[SI]修改SI值第87頁/共175頁(1)CMPS串比較指令格式:CMPSB/CMPSW/CMPSD

執(zhí)行的操作:

源操作數(shù)-目的操作數(shù)即:(DS:[SI])-(ES:[DI]),不保存減法得到的差,但產(chǎn)生新的狀態(tài)標(biāo)志修改SI和DI值4.3.2與有條件重復(fù)前綴配合使用的串指令第88頁/共175頁(2)REPZ/REPE當(dāng)為零/相等時(shí)重復(fù)操作前綴格式:

REPZ/REPE串指令

執(zhí)行的操作:如ZF=1且(CX)≠0,重復(fù)執(zhí)行串指令如ZF=1且(CX)≠0,則:執(zhí)行串操作指令(CX)=(CX)-1返回①ZF=0或(CX)=0,執(zhí)行“REPE/REPZ串指令”的后續(xù)指令

第89頁/共175頁[例4-12]兩個(gè)字符串STRING1、STRING2長度相同,編寫一個(gè)程序,比較它們是否相同。用循環(huán)控制方法編寫的程序段DATA SEGMENTSTRING1 DB 'ALLSTUDENTS……'STRING2 DB 'ALLSTODENTS……'N EQU STRING2-STRING1MESS1 DB 0DH,0AH,'Yes,Stringsarematched.$'MESS2 DB 0DH,0AH,'No,Stringsarenotmatched.$'DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATA第90頁/共175頁START:MOV AX,DATA MOV DS,AX MOV ES,AX LEA SI,STRING1 LEA DI,STRING2 MOV CX,NAGA: MOV AL,[SI] CMP AL,ES:[DI] JNE NO INC SI INC DI LOOP AGA JMP YES第91頁/共175頁NO: LEA DX,MESS2 JMP DISPYES: LEA DX,MESS1DISP: MOV AH,09H INT 21H MOV AX,4C00H INT 21HCODE ENDS END START第92頁/共175頁用帶重復(fù)前綴的字符串比較指令編寫的程序:;裝載DS:SI、ES:DI、CX的程序同上

…… REPZ CMPSB JNE NOYES: LEA DX,MESS1 JMP DISPNO: LEA DX,MESS2DISP: ……第93頁/共175頁(3)REPNZ/REPNE當(dāng)不為零/不相等時(shí)重復(fù)操作前綴該前綴與REPZ/REPE對標(biāo)志位ZF的判別條件剛好相反格式:REPNZ/REPNE串指令執(zhí)行的操作:如果ZF=0且(CX)≠0,重復(fù)串操作

如果ZF=0且(CX)≠0,則:執(zhí)行串操作指令(CX)=(CX)-1重復(fù)上述操作

如果ZF=1或(CX)=0,停止執(zhí)行本指令,執(zhí)行下一條指令

第94頁/共175頁(4)SCAS串掃描指令格式:

SCASB/SCASW/SCASD

執(zhí)行的操作:累加器-目的操作數(shù)字節(jié)操作:(AL)-(ES:[DI])字操作:(AX)-(ES:[DI])修改DI值第95頁/共175頁假設(shè)ES:DI開始有50個(gè)數(shù)據(jù)(占用100B),執(zhí)行下面程序,分別會得到什么結(jié)果?MOVCX,50MOVAX,0REPESCAWMOVCX,50MOVAX,0REPNESCAW第96頁/共175頁4.4

子程序

4.4.1子程序指令

4.4.2子程序定義

4.4.3子程序文件

4.4.4子程序應(yīng)用

4.4.5參數(shù)的傳遞第97頁/共175頁子程序(Subroutine

): 把程序需要完成的任務(wù)分解為若干個(gè)“子任務(wù)”,每個(gè)“子任務(wù)”由一段相對獨(dú)立的程序完成,稱為“子程序”。調(diào)用子程序的程序稱為“主程序”或者“主調(diào)程序”。子程序也稱為“過程”(Procedure),在高級語言里還稱作“函數(shù)”(Function)。第98頁/共175頁子程序結(jié)構(gòu)程序的優(yōu)點(diǎn):1.程序結(jié)構(gòu)清晰,提高了程序的可閱讀性和可維護(hù)性。2.每個(gè)子程序可以獨(dú)立地進(jìn)行調(diào)試,由于程序規(guī)模較小,降低了調(diào)試難度。3.每個(gè)子程序就是一個(gè)具有特定功能的獨(dú)立的程序,提高程序的“可重用性”,提高了軟件開發(fā)效率。第99頁/共175頁圖4-7子程序的調(diào)用和返回

第100頁/共175頁近程子程序:只能被同一個(gè)代碼段里的程序調(diào)用的子程序。由于主程序和子程序處于同一個(gè)代碼段,調(diào)用和返回時(shí)只需要改變IP寄存器的值,CS寄存器的值保持不變。近程子程序的入口地址用16位段內(nèi)偏移地址表示。

第101頁/共175頁遠(yuǎn)程子程序:能夠被不同代碼段的程序調(diào)用,也能被同一代碼段的程序調(diào)用的子程序。調(diào)用這樣的子程序時(shí),需要同時(shí)改變CS和IP寄存器的值,返回時(shí),需要從堆棧里彈出32位的返回地址送入IP,CS寄存器。遠(yuǎn)程子程序的入口地址用16位段基址和16位段內(nèi)偏移地址表示。

子程序的類型在定義時(shí)說明

第102頁/共175頁

4.4.1 子程序指令

1.調(diào)用(Call,CALL)指令

2.返回(Return,RET)指令第103頁/共175頁調(diào)用(Call,CALL)指令

(1)段內(nèi)直接調(diào)用 格式:CALL 子程序名操作:SP←SP-2,SS:[SP]←IP(保存16位返回地址)

IP←子程序入口的偏移地址例如:CALL PROC1

(2)段內(nèi)間接調(diào)用

格式:CALL REG16/MEM16

操作:SP←SP-2,SS:[SP]←IP(保護(hù)16位返回地址)

IP←REG16/MEM16

1.調(diào)用(Call,CALL)指令

第104頁/共175頁例如:調(diào)用名為“PROC1”的近程子程序。

CALL PROC1或者:

LEA CX, PROC1 CALL CX 或者:ADDR_PROC1DWPROC1

;子程序偏移地址放入存儲器字變量

…… CALL ADDR_PROC1 ;調(diào)用近程子程序PROC1或者:…… LEA BX,ADDR_PROC1 CALL WORDPTR[BX] ;調(diào)用近程子程序PROC1第105頁/共175頁(3)段間直接調(diào)用

格式:CALLFARPTR 子程序名操作:SP←SP-2,SS:[SP]←CS SP←SP-2,SS:[SP]←IP

(保存32位返回地址,偏移地址保存在較小地址處)

IP←子程序入口的偏移地址,

CS←子程序入口的段基址CALLFARPTRPROC2

例如:第106頁/共175頁(4)段間間接調(diào)用格式:CALL MEM32操作:SP←SP-2, SS:[SP]←CS SP←SP-2, SS:[SP]←IP IP←[MEM32],CS←[MEM32+2]例如:ADD_PROC2 DD PROC2 ;子程序入口地址放入存儲器雙字變量

…… CALL ADD_PROC2;調(diào)用遠(yuǎn)程子程序PROC2第107頁/共175頁(1)無參數(shù)段內(nèi)返回格式:RET操作:IP←SS:[SP],SP←SP+2(2)有參數(shù)段內(nèi)返回格式:RETD16操作:IP←SS:[SP],SP←SP+2SP←SP+D162.返回(Return,RET)指令第108頁/共175頁(3)無參數(shù)段間返回

格式:RET操作:IP←SS:[SP],SP←SP+2 CS←SS:[SP],SP←SP+2(4)有參數(shù)段間返回格式:RETD16操作:IP←SS:[SP],SP←SP+2 CS←SS:[SP],SP←SP+2 SP←SP+D16第109頁/共175頁4.4.2

子程序的定義

子程序名 PROC [NEAR/FAR]

子程序體子程序名

ENDP

第110頁/共175頁

說明:子程序名應(yīng)為合法的標(biāo)識符,子程序名不能與同一個(gè)源程序中的標(biāo)號、變量名、其它子程序名相同。方括號中的內(nèi)容是子程序的遠(yuǎn)近屬性選項(xiàng),二者可選其一,如果缺省,默認(rèn)為NEAR。用NEAR說明的子程序是“近程子程序”,它只能被與它同一代碼段的程序調(diào)用。用FAR說明的子程序是“遠(yuǎn)程子程序”,它不僅能被與它同一代碼段的程序調(diào)用,也能被其它代碼段的程序調(diào)用。子程序的定義要寫在代碼段內(nèi)。第111頁/共175頁ZEROBYTES PROC ;定義一個(gè)子程序

XOR AX,AX ;AX清零

MOV CX,128 ;循環(huán)次數(shù)送CXZEROLOOP:MOV[BX],AX ;將一個(gè)字存儲單元清零

ADD BX,2 ;修改地址

LOOP ZEROLOOP ;循環(huán)控制

RET ;返回主程序ZEROBYTES ENDP ;子程序結(jié)束思考題:該子程序完成了什么功能?調(diào)用該子程序時(shí),

應(yīng)該先做什么準(zhǔn)備工作?第112頁/共175頁ZEROBYTES:XORAX,AX ;AX寄存器清零

MOV CX,128 ;計(jì)數(shù)器CX置初值ZEROLOOP: MOV [BX],AX ;一個(gè)字單元清零

ADD BX,2 ;修改地址指針,指向下一個(gè)字

LOOP ZEROLOOP ;循環(huán)控制

RET ;結(jié)束程序運(yùn)行,返回主程序子程序也可以簡單地寫成下面的形式:缺點(diǎn):邊界不容易清晰地區(qū)分;只能定義“近程子程序”;

只能被同一代碼段內(nèi)的程序調(diào)用。第113頁/共175頁

CODE SEGMENT ;代碼段開始

MAIN PROCFAR ;主程序開始

…… ;主程序的指令序列

MOV AX,4C00H INT 21H ;返回DOSMAIN ENDP ;主程序結(jié)束

…… ;其它程序CODE ENDS ;代碼段結(jié)束

END MAIN ;源程序結(jié)束用戶編寫的“主程序”也可以看作是由操作系統(tǒng)調(diào)用的一個(gè)子程序:第114頁/共175頁CODE SEGMENT ;代碼段開始MAIN PROCFAR ;主程序開始

PUSH DS ;操作系統(tǒng)的返回點(diǎn)在DS:0 XOR AX,AX PUSH AX ;把32位返回點(diǎn)地址壓入堆棧

…… ;主程序的指令序列

RET ;返回DOSMAIN ENDP ;主程序結(jié)束

…… ;其它程序CODE ENDS ;代碼段結(jié)束

END MAIN ;源程序結(jié)束還可以這樣寫:第115頁/共175頁[例4-13]子程序FRACTOR用來計(jì)算一個(gè)數(shù)的階乘。主程序利用它

計(jì)算1~5的階乘,存入FRA數(shù)組。

DATA SEGMENT FRA DW 5DUP(?)DATA ENDS第116頁/共175頁CODE SEGMENT ASSUMECS:CODE,DS:DATASTART:MOV AX,DATA MOV DS,AX MOV BX,1 ;BX中存放待求階乘的數(shù)

MOVSI,0;SI用作指針

MOV CX,5 ;求階乘次數(shù)(循環(huán)次數(shù))LOOP0:CALL FRACTOR ;調(diào)用FRACTOR求階乘

MOV FRA[SI],AX ;保存結(jié)果(階乘)

INC BX ;產(chǎn)生下一個(gè)待求階乘的數(shù)

ADDSI,2;修改指針

LOOP LOOP0 ;循環(huán)控制第117頁/共175頁

MOV AX,4C00H INT 21HFRACTOR PROC NEAR MOV CX,BX ;待求階乘的數(shù)轉(zhuǎn)入CX寄存器

MOV AX,1 ;“累乘器”置初值1FRALOOP: MUL CX ;累乘

LOOP FRALOOP;循環(huán)控制

RETFRACTOR ENDPCODE ENDS END START思考題:這個(gè)程序存在問題,是什么問題?如何解決?第118頁/共175頁FRACTOR PROC NEAR PUSH CX ;CX壓入堆棧保護(hù)

MOV CX,BX ;待求階乘的數(shù)轉(zhuǎn)入CX寄存器

MOV AX,1 ;“累乘器”置初值1FRALOOP: MUL CX ;累乘

LOOP FRALOOP ;循環(huán)控制

POP CX ;從堆棧里彈出CX的原值

RETFRACTOR ENDPCODE ENDS END START在子程序入口處把相關(guān)寄存器的值入棧保護(hù),程序返回前再恢復(fù)它們的值,這個(gè)操作稱為“保護(hù)現(xiàn)場”和“恢復(fù)現(xiàn)場”。第119頁/共175頁子程序的基本格式:

子程序名 PROC [NEAR/FAR] PUSH …… ;保護(hù)現(xiàn)場(寄存器/存儲器)

PUSH …… ;個(gè)數(shù)根據(jù)具體情況決定

…… ;子程序主體

…… POP …… ;恢復(fù)現(xiàn)場,注意出棧次序

POP …… ;先進(jìn)棧的寄存器后出棧

RET ;返回

子程序名

ENDP第120頁/共175頁4.4.3

子程序文件設(shè)計(jì)一個(gè)子程序之前,首先應(yīng)該明確:子程序的名字;子程序的功能;入口參數(shù):為了運(yùn)行這個(gè)子程序,主程序?yàn)樗鼫?zhǔn)備了哪幾個(gè)“已知條件”?這些參數(shù)存放在什么地方?出口參數(shù):這個(gè)子程序的運(yùn)行結(jié)果有哪些?存放在什么地方?影響寄存器:執(zhí)行這個(gè)子程序會改變哪幾個(gè)寄存器的值?其它需要說明的事項(xiàng)。

上述內(nèi)容連同子程序源代碼等合稱為“子程序文件”。常常把上述內(nèi)容以“程序注釋”的方式書寫在一個(gè)子程序的首部。第121頁/共175頁;名稱:Square;功能:求16Bit無符號數(shù)的平方根;入口參數(shù):16Bit無符號數(shù)在AX中;出口參數(shù):8Bit平方根數(shù)在AL中;影響寄存器:AX(AL)例如,一個(gè)名為“SQUARE”的子程序,用來求一個(gè)無符號數(shù)的平方根,源程序如下:第122頁/共175頁SQUARE PROC NEAR PUSH CX ;保護(hù)現(xiàn)場

PUSH BX MOV BX,AX ;要求平方根的數(shù)送BX MOV AL,0 ;AL中存放平方根,初值0 MOV CX,1 ;CX置入第一個(gè)奇數(shù)1 ;利用公式:N^2=1+3+……+(2N-1)求平方根第123頁/共175頁NEXT: SUB BX,CX JB DONE ADD CX,2 ;形成下一個(gè)奇數(shù)

INC AL ;AL存放已減去奇數(shù)的個(gè)數(shù)

JMP NEXTDONE: POP BX ;恢復(fù)現(xiàn)場

POP CX RET ;返回SQUARE ENDP課內(nèi)練習(xí):編寫主程序,利用SQUARE子程序,求數(shù)26

的平方根,存放在變量ROOT中。第124頁/共175頁4.4.4

子程序應(yīng)用每調(diào)用一次子程序,主程序需要做三件事:(1)為子程序準(zhǔn)備入口參數(shù)(2)調(diào)用子程序(3)處理子程序的返回參數(shù)第125頁/共175頁DATA SEGMENTX DW 59,3500,139,199,77;欲求平方根的數(shù)組ROOT DB 5DUP(?) ;存放平方根內(nèi)存區(qū)DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATASTART:MOV AX,DATA MOV DS,AX[例],為了求5個(gè)無符號數(shù)的平方根,編制主程序如下:第126頁/共175頁

LEA BX,X ;初始化指針

LEA SI,ROOT MOV CX,5 ;設(shè)置計(jì)數(shù)器初值ONE: MOV AX,[BX] ;設(shè)置入口參數(shù)

CALL SQUARE ;調(diào)用子程序

MOV [SI],AL ;保存返回參數(shù)(平方根)

ADD BX,2 ;修改指針

INC SI ;修改指針

LOOP ONE ;循環(huán)控制

MOV AX,4C00H ;返回DOS INT 21H第127頁/共175頁用寄存器傳遞參數(shù)變量(共享數(shù)據(jù)段)傳遞參數(shù)堆棧傳遞參數(shù)

4.4.5

參數(shù)的傳遞第128頁/共175頁傳遞的參數(shù)有兩種類型:(1)值傳遞:把參數(shù)的值放在約定的寄存器或存儲單元傳遞給子程序,或者,由子程序返回給主程序。

如果一個(gè)入口參數(shù)是用值傳遞的,子程序可以使用這個(gè)值,但是無法改變它自身的值。(2)地址傳遞:把參數(shù)事先存放在某個(gè)存儲單元,把這個(gè)存儲單元的地址作為參數(shù)傳遞給子程序。

如果一個(gè)參數(shù)使用它的地址來傳遞,子程序可以改變這個(gè)參數(shù)的值。例如,把存放結(jié)果的存儲單元的地址作為“入口參數(shù)”傳遞給子程序,子程序可以把運(yùn)算結(jié)果直接存入這個(gè)單元。第129頁/共175頁(1)參數(shù)存放在寄存器中(2)參數(shù)存放在主、子程序“共享”的數(shù)據(jù)段內(nèi)(3)參數(shù)存放在堆棧內(nèi)參數(shù)的存放位置,有三種情形:

第130頁/共175頁用寄存器傳遞參數(shù)

.MODEL SMALL.DATAFIBLST DW 1,1,18DUP(?)N DW 20[例4-14]求菲波那契數(shù)列的前n項(xiàng)。菲波那契數(shù)列的前兩項(xiàng)為1,1,以后的每一項(xiàng)都是其前兩項(xiàng)之和。X0=1,X1=1,Xi=Xi-1+Xi-

溫馨提示

  • 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)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論