一、概述
單一的指令其功能比較簡單,要解決一個(gè)實(shí)際問題總是需要一組指令按一定的思路有機(jī)地組合起來才能完成,這樣一組完成特定功能的指令有序集合稱為程序。
(一)程序設(shè)計(jì)的步驟
從具體問題到編好程序要經(jīng)過如下基本步驟:
(1)分析課題——弄清問題的性質(zhì)、目的,已知數(shù)據(jù),運(yùn)算精度以及速度等方面的要求。
(2)確定算法——把實(shí)際問題轉(zhuǎn)化為計(jì)算機(jī)求解的步驟和方法,即算法,而程序是用來描述算法的。
(3)畫流程圖——流程圖是算法的一種直觀而形象的表示方法,是對程序執(zhí)行過程的一種形象化的描述,又稱為框圖。
(4)編寫程序——熟悉8086/8088的指令系統(tǒng)及程序設(shè)計(jì)常用技巧按流程圖編寫程序。要求做到簡單明了、層次清晰、運(yùn)算迅速、少占內(nèi)存。要編寫高質(zhì)量的匯編語言程序,必須加深對指令系統(tǒng)功能的理解,注意內(nèi)存工作單元和工作寄存器的分配。
(5)上機(jī)調(diào)試、修改——可以通過單扳機(jī)或系統(tǒng)機(jī)進(jìn)行調(diào)試、修改直至通過。
(二)程序的基本結(jié)構(gòu)
程序的基本結(jié)構(gòu)有四種:順序結(jié)構(gòu),分支程序結(jié)構(gòu),循環(huán)程序結(jié)構(gòu),子程序結(jié)構(gòu)。現(xiàn)分節(jié)筒述于下。
二、順序結(jié)構(gòu)程序
順序結(jié)構(gòu)的程序又稱簡單程序,這種結(jié)構(gòu)的程序是順序執(zhí)行的, 無分支,無轉(zhuǎn)移,無循環(huán),程序本身的邏輯很簡單,它只依賴于計(jì)算機(jī)能夠順序執(zhí)行指令(語句)的特點(diǎn),只要語句安排的順序正確即可。
例1內(nèi)存中自TABLESQ開始的16個(gè)單元連續(xù)存放著自然數(shù)0到15的平方值,任
給一數(shù)X(0≤X≤15)在XX單元中,查表求出X的平方值,將結(jié)果存入YY單元中。
首先在數(shù)據(jù)段中建立平方表,表的首地址為TABLESO,然后用程序找到X2值在平方表中的位置,即計(jì)算表地址,表地址 = 表起始地址(TABLESQ)+X,據(jù)此可寫出如下程序。
DATASEGMENT
TABLESQDB O,1,4,9,16,25,36,49,
DB 64,81,100,121,144,169,225
XXDB?
YYDB?
DATAENDS
STACKSEGMENT PARA STACK‘STACK’
DB50 DUP(?)
STACKENDS
CODESEGMENT
ASSUMECS:CODE,DS:DATA,SS:STACK
STARTPROC FAR**
BEGIN:PUSH DS**
MOV,AX,0**
PUSH AX**
MOVAX,DATA
MOVDS,AX
MOVBX,OFFSET TABLESQ
MOVAH,0
MOVAL,XX
ADDBX,AX
MOVAL,[BX]
MOVYY,AL
RET**
STARTENDP**
CODEENDS
END BEGIN
其中帶 ** 的六行語句的作用是為了在用戶程序運(yùn)行結(jié)束后,正確返回操作系統(tǒng)。匯編語言源程序經(jīng)過匯編、連接后生成 .EXE文件,可在DOS下直接鍵入文件名運(yùn)行,例如命令 A>EXAMPLE 將把帶有.EXE的文件EXAMPLE裝入內(nèi)存,并從程序中指定地址開始運(yùn)行。裝入文件并設(shè)置啟動地址是由操作系統(tǒng)的COMMAND.COM文件完成的。COMMAND.COM文件在裝入.EXE文件前,首先確定最低可用地址作為被裝入程序的可用內(nèi)存起點(diǎn)(該區(qū)段稱為程序段)并在程序內(nèi)從段內(nèi)偏移地址處開辟100H字節(jié)的程序段前綴(PSP),在該P(yáng)SP的前兩字節(jié)存放一條 INT 20H 指令(即退出當(dāng)前程序返回操作系統(tǒng))。而COMMAND.COM把.EXE文件裝入后,自動設(shè)置DS和ES寄存器指向程序段前綴,即此時(shí)的DS和ES值為程序段前綴之段基值。用戶程序結(jié)束為RET,為使RET后程序轉(zhuǎn)向程序段前綴中INT 20H指令,必須使CS為程序段前綴的段基值,IP為INT 20H的段內(nèi)偏移值00H,因此必須把用戶程序設(shè)計(jì)為過程,即加下START PROC FAR,在用戶程序的前三條指令寫入PUSH DS,MOV AX,0和PUSH AX,把DS = 程序段前綴之段基值,AX = 00H進(jìn)棧,在用戶程序最后用RET指令出棧到CS和IP,以保證程序轉(zhuǎn)向INT 20H,進(jìn)而返回操作系統(tǒng)。
代碼段結(jié)束的處理還可用DOS系統(tǒng)功能調(diào)用,在結(jié)尾處安排如下兩條指令
MOV AH、4CH
INT 21H
執(zhí)行至此,返回調(diào)用程序,常用于應(yīng)用DEBUG進(jìn)行程序調(diào)試,可返回DEBUG。這 時(shí),可不用把用戶程序設(shè)計(jì)為過程,即去除帶 ** 的六行語句。
例2把非壓縮十進(jìn)制數(shù)轉(zhuǎn)換為壓縮十進(jìn)制數(shù),被轉(zhuǎn)換數(shù)存放在DATl開始的兩個(gè)單元,轉(zhuǎn)換后的數(shù)存回DATl單元。
程序如下:
MOV AX,DATI;(AX)=0109H
MOV CL,4;(CL)=4
SAL AH,CL;(AH)=10H
ROL AX,CL;(AX)=0091H
ROL AL,CL;(AL)=19H
MOV BYTE PTR DATl,AL;(DATl)=19H
┅
DATl DW 0109H
三、分支結(jié)構(gòu)程序
在實(shí)際的程序設(shè)計(jì)中,始終是順序執(zhí)行的情況是很少的,大部分程序在執(zhí)行過程中,總是要求計(jì)算機(jī)作出一些判斷,井根據(jù)判斷作出不同的處理,這就引出了分支程序的概念。
(一)分支程序的二要素
分支結(jié)構(gòu)程序是具有判斷和轉(zhuǎn)移功能的程序。
1.判斷——根據(jù)運(yùn)算結(jié)果的狀態(tài)標(biāo)志
判斷前一定要經(jīng)過運(yùn)算(能影響狀態(tài)標(biāo)志的運(yùn)算),狀態(tài)標(biāo)志反映了運(yùn)算結(jié)果的特性。這些狀態(tài)標(biāo)志是:進(jìn)位標(biāo)志CF、奇偶標(biāo)志PF、零標(biāo)志ZF、符號標(biāo)志SF以及溢出標(biāo)志OF。
2.轉(zhuǎn)移 — 主要由條件轉(zhuǎn)移指令來實(shí)現(xiàn)(也可用無條件轉(zhuǎn)移指令JMP)
在8086/8088的指令系統(tǒng)中,條件轉(zhuǎn)移指令可分為兩大類,一類是按單標(biāo)志位來判斷的,如JAE,JC,JZ,JO,JS等;另一類是按多標(biāo)志位來判斷,如JGE,JG,JA等,詳見表3-6所示。
分支結(jié)構(gòu)程序框圖如圖4—1所示。
(二)利用比較轉(zhuǎn)移指令實(shí)現(xiàn)分支
這是實(shí)現(xiàn)分支的一種常用方法,用于比較、判斷的指令是CMP(比較指令)、CMPS(串比較指令)以及SCAS(串搜索指令)等。轉(zhuǎn)移指令已如前述。而分支的次數(shù)可由具體問題決定是單重分支還是多重分支。n次判斷可形成n+l路分支。
例3符號函數(shù)的處理
有一符號函數(shù)
1,當(dāng) X>O(-128≤X≤127)
Y =O,當(dāng) X=0
-1, 當(dāng) X<O
設(shè)給定值x存放于LY單元,函數(shù)Y值存放于YY單元,則按X的不同取值給Y賦值的程序如下:
MOV AL.XX
CMP AL,0
JGE BIGR
MOV AL,0FFH
MOV YY,AL;X<0時(shí),—1送入YY單元
HLT
BIGR:JE EQUL
MOV AL,1
一MOV YY,AL;X>O時(shí),l送人YY單元
HLT
EQUL:MOVYY,AL;X=O時(shí),O送人YY單元
HLT
這是一個(gè)多重分支的符號函數(shù)賦值程序,其流程圖見圖4-2 所示。
例4數(shù)據(jù)塊傳送程序
要求把內(nèi)存中某一區(qū)域的源數(shù)據(jù)塊傳送到另一區(qū)域。在編寫該程序時(shí),必須判別一下源數(shù)據(jù)區(qū)同目的數(shù)據(jù)區(qū)之間有無重疊,以決定是增量傳送還是減量傳送。程序清單如下:
DATASEGMENT
STRGDB l000 DUP(?)
STGlEQU STRG+7
STG2EQU STRG+25
SIRSEEQU 50
DATAENDS
STACKSEGMENT PARA STACK‘STACK’
STARNDB l000 DUP(?)
STACKENDS
COSEGSEGMENT
ASSUME CS:COSEG,DS:DATA,ES:DATA,SS:STACK
GOOPROCFAR
BEGIN: PUSH DS
MOVAX,0
PUSH AX
MOVAX,DATA
MOVDS,AX
MOVES,AX
MOVCX,STRSE
MOVSI,OFFSET STGl
MOVDI,OFFSET STG2
CLD;增量方式
PUSHI SI
ADDSI,STRSE-1
CMPSI,DI
POPSI
JBOK
STD;減量方式傳送
ADDDI,STRSE-1;指向數(shù)據(jù)塊底部
ADDSI,STRSE-1
OK:REP MOVSB;重復(fù)傳送50個(gè)數(shù)據(jù)
RET
GOOENDP
COSEGENDS
END BEGIN
(三)利用跳轉(zhuǎn)表實(shí)現(xiàn)分支
1.跳轉(zhuǎn)表的建立
在內(nèi)存的一個(gè)連續(xù)區(qū)中,連續(xù)存放一系列跳轉(zhuǎn)地址、跳轉(zhuǎn)指令或關(guān)鍵字,組成一個(gè)決
定程序分支的跳轉(zhuǎn)表。
例5某工廠有8種產(chǎn)品的加工程序RO到R7分別存放在以SBRO,SBRl,…,SBR7為首地址的內(nèi)存區(qū)域中,這8個(gè)首地址的偏移量連續(xù)存放在以BASE為首地址跳轉(zhuǎn)表內(nèi),如圖4-3 所示。
2.跳轉(zhuǎn)表的使用
上例中,8種產(chǎn)品的編號為0,1,2,…,7 如果已知目前要加工的產(chǎn)品編號,要求編寫程序,利用跳轉(zhuǎn)表自動轉(zhuǎn)入該產(chǎn)品的加工程序。
在跳轉(zhuǎn)表已知的情況下,關(guān)鍵問題要計(jì)算所要求的加工程序的入口地址在跳轉(zhuǎn)表中的地址,即計(jì)算表地址。從圖 4-3可見:
表地址=表基地址+偏移量
表基地址即跳轉(zhuǎn)表的首地址,偏移量即對應(yīng)的程序入口地址在表中的地址與表基地址
的距離。在本例中,分析表的結(jié)構(gòu)可見,偏移量=產(chǎn)品編號 * 2,已知偏移量后,即可求出表地址。據(jù)此可寫出[例5]的程序清單
DATASEGMENT
BASEDW SBR0,SBRl,SBR2,SBR3
DW SBR4,SBR5,SBR6,SBR7
BNDB ?
DATAENDS
STACK SEGMENT PARA STACK ‘STACK’
DBl00 DUP(?)
STACK ENDS
COSEGSEGMENT
ASSUME CS:COSEG,DS:DATA,SS:STACK
START PROC FAR
BEGIN:PUSHDS
MOVAX,O
PUSHAX
MOVAX,DATA
MOVDS,AX
MOVAL,BiN
MOVAH.O
ADDAL,AL
MOVBX,OFFSETBASE
ADDBX,AX
MOVAX,[Bx]
JMPAX
RET
STARTENDP
COSEGENDS
END BEGIN
3.根據(jù)跳轉(zhuǎn)表內(nèi)指令分支
在計(jì)算機(jī)系統(tǒng)的監(jiān)控程序,鍵盤管理程序中經(jīng)常要用到跳轉(zhuǎn)表。在跳轉(zhuǎn)表中既可存放跳轉(zhuǎn)地址(如例5),也可存放一系列的跳轉(zhuǎn)指令JMP。
例6有一監(jiān)控程序的鍵盤程序控制12個(gè)命令鍵——執(zhí)行鍵(EXEC)、存儲器檢查鍵(MEM)等等,按下任一命令鍵相當(dāng)于發(fā)出一條鍵盤命令,而這些命令的實(shí)現(xiàn)分別由監(jiān)控程序中的12個(gè)于程序完成,這些子程序的入口地址分別為ADR0,ADRl,…,ADRll。據(jù)此可以組成命令鍵跳轉(zhuǎn)表如圖4-4所示。該命令鍵跳轉(zhuǎn)表存放在以BASE0為首地址的內(nèi)存區(qū)域中,表內(nèi)存放著12條轉(zhuǎn)移指令:
JMPADR0,JMPADRl,…,JMP ADRll。
設(shè)12個(gè)命令鍵的編號分別為0 ~ 11。命令跳轉(zhuǎn)表中每三個(gè)單元存放一條轉(zhuǎn)移指令,如果命令鍵的編號X已送入寄存器AL,則實(shí)現(xiàn)轉(zhuǎn)向相應(yīng)的命令子程序的程序如下
MOVAH,0
MOVBL,AL
ADDAL,AL
ADDAL,BL
ADDAL, BL
MOVBX,OFFSET BASE0
ADDBX,AX;表地址計(jì)算
JMPBX
四、循環(huán)結(jié)構(gòu)程序
(一)概述
1.循環(huán)程序
實(shí)現(xiàn)重復(fù)執(zhí)行某一段程序的程序結(jié)構(gòu)稱為循環(huán)程序。用來處理帶重復(fù)性的問題,可以縮短源程序及目標(biāo)程序。
循環(huán)結(jié)構(gòu)程序的框圖之一如圖4-5所示。
循環(huán)程序由五部分組成:
(1)初始化部分——這是循環(huán)的準(zhǔn)備部分,為程序操作、地址指針、循環(huán)計(jì)數(shù)、結(jié)束條件等設(shè)置初始值。
(2)循環(huán)工作部分——這是循環(huán)程序的主體,完成程序的基本操作,循環(huán)多少次,這部分的語句就執(zhí)行多少次。
(3)循環(huán)修改部分——修改循環(huán)工作部分的變量地址等,為下一輪重復(fù)操作作準(zhǔn)備。
(4)循環(huán)控制部分——修改計(jì)數(shù)器或判斷循環(huán)結(jié)束條件以決定是繼續(xù)循環(huán)還是終止循環(huán),是典型的分支結(jié)構(gòu),不過繼續(xù)
循環(huán)的分支去向是循環(huán)體的頭部。通常把循環(huán)工作部分稱為循環(huán)體,循環(huán)體的第一條指令為循環(huán)體的頭部。
(5)循環(huán)結(jié)束部分——循環(huán)終止后,對循環(huán)結(jié)果的處理部分。
2.循環(huán)程序的幾種結(jié)構(gòu)形式
循環(huán)程序除圖4-5所示的基本結(jié)構(gòu)形式外,還有兩種常用的結(jié)構(gòu)形式,如圖4-6和圖
4-7所示。
這兩種結(jié)構(gòu)的特點(diǎn)是工作部分放在循環(huán)控制部分之后,這樣可以允許循環(huán)次數(shù)為零的循環(huán)程序或不需要循環(huán)時(shí)不進(jìn)入循環(huán)工作部分。
3.循環(huán)程序分類
(1)按循環(huán)控制條件分類
1)計(jì)數(shù)循環(huán)——重復(fù)次數(shù)已知,用計(jì)數(shù)值控制循環(huán)的開始與終止。
2)條件控制循環(huán)——重復(fù)次數(shù)未知或不確定,需找出循環(huán)控制的條件。
(2)按循環(huán)體內(nèi)結(jié)構(gòu)分類
1)單重循環(huán)——循環(huán)體內(nèi)只是順序程序或分支程序,不再有循環(huán)程序。
2)多重循環(huán)——循環(huán)體內(nèi)再套有循環(huán)程序??砂阎貜?fù)處理部分獨(dú)立出來,前面加上循環(huán)準(zhǔn)備,后面加上結(jié)束判斷。
4.循環(huán)程序設(shè)計(jì)要點(diǎn)
循環(huán)程序設(shè)計(jì)要點(diǎn)可歸結(jié)為兩點(diǎn):
(1)怎樣把求解的問題變?yōu)檠h(huán)結(jié)構(gòu)的程序類型——怎樣實(shí)現(xiàn)重復(fù),即計(jì)算方案的循環(huán)化。這里循環(huán)工作部分的設(shè)計(jì)尤為重要,因?yàn)檫@是多次重復(fù)的部分,注意程序的精練,及循環(huán)體頭部的確定。
(2)怎樣使循環(huán)準(zhǔn)確地執(zhí)行完畢,這就要注意循環(huán)控制部分的設(shè)計(jì)。特別是對條件控制的循環(huán),注意設(shè)置循環(huán)結(jié)束標(biāo)志。
(二)循環(huán)程序舉例
例7計(jì)算Y=∑ai, 0≤i≤100
有100個(gè)數(shù)a1,a2,…,a100,求這100個(gè)數(shù)之和(設(shè)和值不大于2個(gè)字節(jié))。采用循環(huán)結(jié)構(gòu)可寫出如下程序:
DATASEGMENT
TABLDW a1,a2,…,a10
DW all,a12,…,a20
…
DW a91,a92,…,a100
YYDW ?
DATAENDS
STACKSEGMENT PARASTACK‘STACK’
DBl00 DUP(?)
STACKENDS
CODESEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK
GOPROC FAR
BEGIN:PUSH DS
MOV AX,O
PUSH AX
MOV AX,DATA
MOV DS, AX
MOV AX,0
MOV BX, OFFSET TABL
MOV CX, 100
LOP:ADD AX,[Bx]
INC BX
INC BX
DEC CX
JNZ LOP
MOV YY,AX
RET
GO:ENDP
CODEENDS
例8統(tǒng)計(jì)數(shù)組中負(fù)元素的個(gè)數(shù)
數(shù)據(jù)段的定義如下:
DATASEGMENT
D1 DB -1,-3,5,6,-9,…
COUNT EQU $-D1
RS DW ?
DATAENDS
代碼段程序?yàn)?
CODE SEGMENT
ASSUME CS:CODE,SS:STACK, DS:DATA
START PROC FAR
BEGING: PUSH DS
MOV AX,0
PUSH AX
MOV AX,DATA
MOV DS,AX
MOV BX,OFFSET D1;建立數(shù)據(jù)指針
MOV CX,COUNT;置計(jì)數(shù)器初值
MOV DX,0;置結(jié)果初值
LOP1: MOV AL,[BX]
CMP AL,0
JGE JUS
INC DX
JUS:INC BX
DEC CX
JNZ LOP1
MOV RS,DX
RET
START ENDP
CODE ENDS
以上兩例都是‘‘先執(zhí)行,后判斷”的結(jié)構(gòu)。
例9寄存器AX中有一個(gè)16位二進(jìn)制數(shù),編程統(tǒng)計(jì)其中“1”的個(gè)數(shù),結(jié)果存放在
CX中。
本例最好采用“先判斷、后執(zhí)行”的結(jié)構(gòu),即先檢查凡x中有無為“1”的位。則代碼段的有關(guān)程序如下:
MOVCX, 0
LOP:ANDAX, AX
JZSTP
SALAX, 1
JNCLOP
INCCX
JMPLOP
STP: HLT
例10軟件延時(shí)程序如下:
SOFTDLY PROC
MOV BL,10
DELAY: MOV CX, 2801
WAIT:LOOP WAIT
DEC BL
JNZ DELAY
RET
SOFTDLY ENDP
這是一個(gè)二重循環(huán)結(jié)構(gòu),內(nèi)循環(huán)即WAIT:LOOPWAIT,每個(gè)內(nèi)循環(huán)可實(shí)現(xiàn)延時(shí)10ms左右,外循環(huán)人口為DELAY:MOV CX,2801,共進(jìn)行10次,總的延時(shí)時(shí)間約lOOms。
注意:可以從內(nèi)循環(huán)直接跳到外循環(huán),但不能從外循環(huán)直接跳進(jìn)內(nèi)循環(huán)。特別要注意100循環(huán)體頭部,防止死循環(huán)。
五、子程序
(一)概述
1.子程序結(jié)構(gòu)
如果在一個(gè)程序中的多個(gè)地方或在多個(gè)程序中都要用到同一段程序,可以把該程序段獨(dú)立出來存放在內(nèi)存的某一區(qū)域以供其他程序調(diào)用,這段程序稱為子程序或過程。可見子程序是可供其他程序調(diào)用的獨(dú)立的、相對固定的程序段。調(diào)用子程序的程序體稱為主程序或調(diào)用程序。在實(shí)用中總把常用的子程序標(biāo)準(zhǔn)化后存放在一個(gè)內(nèi)存區(qū)中,稱為“子程序庫”。
(1)結(jié)構(gòu)。子程序的第一個(gè)語句前必須有“過程名”——入口地址的符號表示,出口是返回指令RET。
(2)調(diào)用與返回。主程序通過書寫調(diào)用指令CALL后跟子程序的入口地址來調(diào)用子程序,8086/8088允許子程序在現(xiàn)行代碼段中(子程序名為NEAR類型),也可以不在現(xiàn)行代碼段中(子程序名為FAR類型)。為了保證正確返回,RET指令的類型,必須與CALL指令的類型相匹配。
1)調(diào)用指令中的目標(biāo)地址有兩種表示方法:
a.直接調(diào)用,目標(biāo)地址就在指令中。例如:CALL NEAR-PRG。
b.間接調(diào)用,目標(biāo)地址在由指令指定的寄存器或內(nèi)存單元中。例如:CALL DWORD PTR[BX]對段內(nèi)的直接調(diào)用而言,CALL指令首先將SP減2,使斷點(diǎn)的IP棧,從指令中得到的目標(biāo)過程的相對偏移量(最大不能越界)加到IP上。對段內(nèi)的間接調(diào)用而言,以CALL AX為例,SP減2,IP進(jìn)棧,AX→IP。
對段間的直接調(diào)用而言,SP減2,現(xiàn)行代碼段寄存器CS的內(nèi)容進(jìn)棧,CS由指令中目標(biāo)過程的段基值代入。SP再減2,IP進(jìn)棧,然后將指令中的偏移地址代入IP。
對段間的間接調(diào)用而言,SP減2,把現(xiàn)行的CS值進(jìn)棧,CS由指令指定的雙字存儲器指針的第二個(gè)字的內(nèi)容代入,SP再減2,IP進(jìn)棧,然后IP由指令中指定的雙字指針的第一個(gè)字的內(nèi)容代入。雙字存儲器由數(shù)據(jù)段定義。
2)返回指令RET也有兩種情況:
a. 段內(nèi)返回指令,把SP所指的堆棧頂部的一個(gè)字的內(nèi)容彈回IP,SP加2。
b.段間返回指令,把SP所指的堆棧頂部的兩個(gè)字的內(nèi)容,先彈回IP,后彈回CS,SP加4。
2.子程序文件
子程序應(yīng)以文件形式編寫,子程序文件由子程序說明和子程序構(gòu)成。
(1)子程序說明。子程序說明包括如下部分:
1)功能描述:包括子程序名稱、功能,以及性能指標(biāo)(如執(zhí)行時(shí)間)等o
2)所用寄存器和存儲單元。
3)子程序的入口、出口參數(shù)。
4)子程序中又調(diào)用的其他子程序。
5)調(diào)用實(shí)例(可無)。
子程序說明舉例如下:
;子程序PTOB
;兩位十進(jìn)制數(shù)(BCD碼)轉(zhuǎn)換成二進(jìn)制數(shù)
;入口參數(shù):AL中存放被轉(zhuǎn)換數(shù)
;出口參數(shù):CL中存放轉(zhuǎn)換后的二進(jìn)制數(shù)
;所用寄存器:BX
;執(zhí)行時(shí)間:0.06ms
(2)子程序。在8086/8088中,子程序本身常以過程形式存放在代碼段中,以一個(gè)過程名開始,以RET指令結(jié)束。
例如: DTOBPROC
…
RET
DTOBENDP
3.子程序應(yīng)用中應(yīng)注意的問題
(1)主程序與子程序的連接。主程序與子程序的連接由下例可見:
例如;
CODESEGMENT
START:…
MOV AL,XX;被轉(zhuǎn)換的數(shù)在XX單元
PUSH BX
CALL DTOB
MOV YY,CL;轉(zhuǎn)換結(jié)果存于YY單元
POP BX
…
DTOBPROC
RET
DTOBENDP
CODEENDS
END START
(2)子程序中所用寄存器及工作單元內(nèi)容的保護(hù)。為了不破壞原有信息,對于在子程序中要用到的某些寄存器和存儲單元的內(nèi)容,必須壓入堆棧加以保護(hù),也可存入一些空閑單元或某些目前不用的寄存器中。稱為現(xiàn)場信息的保護(hù)。保護(hù)可以在子程序中實(shí)現(xiàn),可在主程序中實(shí)現(xiàn),一般在子程序中實(shí)現(xiàn)保護(hù)比較好。而對于用作中斷服務(wù)的子程序,則一定在子程序中安排保護(hù)指令,因?yàn)橹袛嗟某霈F(xiàn)是隨機(jī)的,無法在主程序中安排保護(hù)程序。
(3)參數(shù)的傳遞。主程序與子程序通常需要交換信息,在多數(shù)情況下主程序需要向子程序傳遞參數(shù),子程序執(zhí)行的結(jié)果要傳送給主程序。子程序清單中的人口參數(shù)使子程序?qū)Σ煌臄?shù)進(jìn)行處理,出口參數(shù)可送出不同的結(jié)果。
參數(shù)傳遞一般有三種方法:
1)用寄存器傳遞,適用于參數(shù)較少的情況;
2)用參數(shù)表傳遞,適用于參數(shù)較多的情況,要求事先建立參數(shù)表,參數(shù)表一般建立在內(nèi)存中。
3)用堆棧傳遞,適用于參數(shù)多并子程序有嵌套、遞歸調(diào)用的情況,主程序?qū)?shù)壓入堆棧,子程序中將參數(shù)從堆棧彈出。
4.子程序嵌套和子程序遞歸
(1) 子程序嵌套 。子程序調(diào)用別的子程序,稱為嵌套,。嵌套的層次只受空間的大小
的限制。
(2)子程序遞歸。子程序直接或間接地調(diào)用子程序自身,稱為遞歸。
(二)子程序結(jié)構(gòu)舉例
例11數(shù)據(jù)段定義了兩個(gè)數(shù)組ARYl和,ARY2,編一程序分別求此兩數(shù)之和。主程序和過程分別安排在兩個(gè)不同的段中,因此過程應(yīng)是FAR類型。
該程序清單如下
STACKSEGMENT PARA STACK
DW 20 DUP(?)
STACKENDS
DATASEGMENT
ARY1 DB 100 DUP(?)
SUM1 DW ?
ARY2 DB 50 DUP(?)
SUM2 DW ?
DATAENDS
MAINSEGMENT;主程序段
ASSUME CS:MAIN, DS:DATA,SS:STACK
STR:PUSH DS
MOV AX,0
PUSH AX
MOV AX,DATA
MOV DS,AX
MOV AX,SIZE ARY1
PUSH AX;SUM過程的入口參數(shù)1 進(jìn)棧
MOV AX,OFFSET ARY1
PUSH AX
CALL SUM
…
MOV AX,SIZE ARY2
PUSH AX;SUM過程的入口參數(shù)2 進(jìn)棧
MOV AX,OFFSET ARY2
PUSH AX
CALL SUM
HIT
MAINENDS
PROCESEGMENT; 過程段
ASSUMECS:PROCE,DS:DATA,SS:STACK
SUMPROC FAR
PUSH AX
PUSH BX
PUSH CX
PUSH BP
N40V BP,SP
PUSHF
MOV CX,[BP+14]
MOV BX,[BP+12]
MOV AX,0
AND:ADD AL,[BX]
INC BX
ADC AH,0
LOOP ADN
MOV[BX],AX;數(shù)組之和送到結(jié)果區(qū)
POPF;恢復(fù)現(xiàn)場
POP BP
POP CX
POP BX
POP AX
RET 4;返回并廢除參數(shù)1和2
SUMENDP
PROCEENDS
END STR
從程序清單可見主程序向過程的參數(shù)傳遞是通過堆棧實(shí)現(xiàn)的,程序執(zhí)行過程中堆棧變化如圖所示。
圖4-8例u中堆棧變化情況
程序中出現(xiàn)RET 4,該指令的功能是返回后,SP再加 4
例12求n!
算法是
n! =n(n-1)!當(dāng)n>0時(shí);
1當(dāng)n=0時(shí)
設(shè)數(shù)n存放在AL中,n! 存放在BX中。
;主程序
MAIN: MOV AX,3;設(shè)n=3
CALL FACT
X1: MOV BX,DX
HLT
;階乘子程序
;人口參數(shù):AL中存放n
;出口參數(shù):DX中存放n!
;所用寄存器:CX
FACTPROC
CMP AL,0
JNZ IIA
MOV DL,1
RET;①
IIA: PUSH AX
DECAL
CALL FACT
X2:POP CX
CALL MULT
X3:MOV DX,AX
RET;②
FACTENDP
;無符號字節(jié)數(shù)乘法子程序
;入口參數(shù):CL、DL中各為一乘數(shù)
;出口參數(shù):AX中為乘積
MULTPROC
…
RET;③
MULTENDP
該程序既包括子程序嵌套,也包括子程序遞歸。該子程序名為FACT,嵌套子程序即
FACT調(diào)用另一子程序MULT(無符號字節(jié)數(shù)乘法子程序),遞歸子程序即FACT調(diào)用FACT。注意三個(gè)RET指令的作用。
聲明:
(一)由于考試政策等各方面情況的不斷調(diào)整與變化,本網(wǎng)站所提供的考試信息僅供參考,請以權(quán)威部門公布的正式信息為準(zhǔn)。
(二)本網(wǎng)站在文章內(nèi)容來源出處標(biāo)注為其他平臺的稿件均為轉(zhuǎn)載稿,免費(fèi)轉(zhuǎn)載出于非商業(yè)性學(xué)習(xí)目的,版權(quán)歸原作者所有。如您對內(nèi)容、版權(quán)等問題存在異議請與本站聯(lián)系,我們會及時(shí)進(jìn)行處理解決。
相關(guān)推薦
2022年浙江自考《當(dāng)代中國政治制度》復(fù)習(xí)筆記匯總
09-152023年浙江自考西方行政學(xué)說史復(fù)習(xí)資料:西方行政學(xué)的產(chǎn)生
03-022023年10月浙江自考傳播學(xué)概論復(fù)習(xí)資料:有限效果論
08-302022年浙江自考中國古代文學(xué)史(一)第三編第九章復(fù)習(xí)資料
10-31自考輔導(dǎo)資料:2021年10月《學(xué)前教育史》—論幼稚師范教育
06-052023年4月浙江自考中外教育簡史復(fù)習(xí)筆記:英國近代教育制度
12-08自考輔導(dǎo)資料:2019年10月《美學(xué)》知識點(diǎn)-崇高的內(nèi)涵與特點(diǎn)
09-17自考輔導(dǎo)資料:2021年10月《學(xué)前教育史》—雅典的學(xué)前教育
06-072023年4月浙江自考英美文學(xué)選讀復(fù)習(xí)筆記:William Butler Yeats
12-082023年4月浙江自考新聞學(xué)概論復(fù)習(xí)筆記:社會主義新聞事業(yè)對從業(yè)者的基本要求
12-05與考生自由互動、并且能直接與專業(yè)老師進(jìn)行交流解答。
與考生自由互動、并且能直接與專業(yè)老師進(jìn)行交流解答。