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

下載本文檔

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

文檔簡介

1、第第5章章 匯編語言程序設(shè)計(jì)匯編語言程序設(shè)計(jì)主要內(nèi)容主要內(nèi)容l順序、分支、循環(huán)結(jié)構(gòu)程序設(shè)計(jì)順序、分支、循環(huán)結(jié)構(gòu)程序設(shè)計(jì)l子程序設(shè)計(jì)子程序設(shè)計(jì)l轉(zhuǎn)移指令、循環(huán)指令和子程序偽指令轉(zhuǎn)移指令、循環(huán)指令和子程序偽指令教學(xué)要求教學(xué)要求l掌握:掌握:(1)分支程序的概念、結(jié)構(gòu)和設(shè)計(jì)(2)循環(huán)程序的概念、結(jié)構(gòu)和設(shè)計(jì)(3)子程序的概念、結(jié)構(gòu)和設(shè)計(jì)l了解:了解: 轉(zhuǎn)移表法和地址表法多分支程序的設(shè)計(jì)原理;多重循環(huán)程序的結(jié)構(gòu)形式,內(nèi)層循環(huán)與外層循環(huán)遵守的層次結(jié)構(gòu)規(guī)則,參數(shù)修改對各層的相互影響;匯編遞歸程序方法。 編制一個(gè)匯編語言程序的步驟編制一個(gè)匯編語言程序的步驟 (1)分析題意,確定算法。(2)根據(jù)算法,確定程序流

2、程或畫出程序框圖。(3)根據(jù)流程或框圖編寫程序。(4)上機(jī)調(diào)試程序。5.1 順序程序設(shè)計(jì)順序程序設(shè)計(jì)l順序結(jié)構(gòu)是最簡單的程序結(jié)構(gòu),程序的執(zhí)行順序就是指令的編寫順序,所以,安排指令的先后次序就顯得至關(guān)重要。 【例】【例】 設(shè)置光標(biāo)到屏幕左上角設(shè)置光標(biāo)到屏幕左上角SET_CUR PROCMOV AH,2 ;設(shè)置光標(biāo)位置功能MOV BH,0 ;頁號MOV DX,0 ;行DH,列DLINT 10H ;BIOS輸出字符中斷 RETSET_CUR ENDP 這個(gè)程序段是順序執(zhí)行的,一條指令執(zhí)行后順序執(zhí)行緊接其后的另一條指令。【例】【例】 設(shè)在設(shè)在X單元中存放一個(gè)單元中存放一個(gè)07之間的整數(shù),用查表法求出其

3、平之間的整數(shù),用查表法求出其平方值,并將結(jié)果存入方值,并將結(jié)果存入Y單元。單元。l分析:根據(jù)題意,首先將07所對應(yīng)的平方值存入連續(xù)的8個(gè)單元中,構(gòu)成一張平方值表,其首地址為SQTAB。l由表的存放規(guī)律可知:表首址SQTAB與X單元中的數(shù)i之和,正是i2所在單元的地址。DATA SEGMENT ;數(shù)據(jù)段定義SQTAB DB 0,1,4,9,16,25,36,49 ;平方值表X DB 5Y DB ?DATA ENDSSTACK SEGMENT PARA STACK STACKTAPN DB 100 DUP (?)TOP EQU LENGTH TAPNSTACK ENDSCODE SEGMENTAS

4、SUME CS:CODE,DS:DATA,SS:STACKSQRTSUB PROC FARPUSH DSSUB AX,AXPUSH AXMOV AX,DATAMOV DS,AXMOV AX,STACKMOV SS,AXMOV AL,X ;取數(shù)iMOV AH,0MOV BX,OFFSET SQTAB ;BX表首址ADD BX,AXMOV AL,BX ;取i2并保存MOV Y,ALRETSQRTSUB ENDPCODE ENDSEND SQRTSUB5.2 分支程序設(shè)計(jì)分支程序設(shè)計(jì)l分支結(jié)構(gòu)是一種非常重要的程序結(jié)構(gòu),也是實(shí)現(xiàn)程序功能選擇所必要的程序結(jié)構(gòu)。l由于匯編語言需要用轉(zhuǎn)移指令來實(shí)現(xiàn)分支結(jié)構(gòu),

5、而轉(zhuǎn)移指令肯定會破壞程序的結(jié)構(gòu),所以,編寫清晰的分支結(jié)構(gòu)是掌握該結(jié)構(gòu)的重點(diǎn)。l計(jì)算機(jī)可根據(jù)不同條件進(jìn)行邏輯判斷,從而選擇不同的程序流向。程序的流向是由CS和IP值決定的,當(dāng)程序的轉(zhuǎn)移僅在同一段內(nèi)進(jìn)行時(shí),只需修改偏移地址IP的值;如果程序的轉(zhuǎn)移是在不同段之間進(jìn)行的,則段基址CS和偏移地址IP的值均需要修改。 5.2.1 轉(zhuǎn)移指令轉(zhuǎn)移指令l轉(zhuǎn)移指令是匯編程序員經(jīng)常要用到的一組指令。在高級語言中,時(shí)常有“盡量不要使用轉(zhuǎn)移指令語句”的勸告。但是,在匯編語言程序中,不但要使用轉(zhuǎn)移指令,而且還要靈活運(yùn)用,因?yàn)橹噶钕到y(tǒng)中有大量的轉(zhuǎn)移指令。l轉(zhuǎn)移指令分為無條件轉(zhuǎn)移指令和有條件轉(zhuǎn)移指令。 無條件轉(zhuǎn)移指令無條件轉(zhuǎn)

6、移指令JMP l無條件轉(zhuǎn)移指令JMP指令是從程序當(dāng)前執(zhí)行的地方無條件地轉(zhuǎn)移到另一個(gè)地方執(zhí)行。 指令格式JMP 地址表達(dá)式指令功能無條件地轉(zhuǎn)移到由地址表達(dá)式所確定的目標(biāo)單元,本指令對標(biāo)志位無影響4種方式段內(nèi)直接轉(zhuǎn)移段內(nèi)間接轉(zhuǎn)移段間直接轉(zhuǎn)移段間間接轉(zhuǎn)移說 明這是一種相對尋址方式。它轉(zhuǎn)移的目標(biāo)地址是當(dāng)前IP內(nèi)容加上一個(gè)8位相對位移量(DISP), DISP是匯編程序在匯編源程序時(shí),根據(jù)目標(biāo)地址和當(dāng)前IP之間的距離自動(dòng)生成的它轉(zhuǎn)移的目標(biāo)地址可通過寄存器或存儲單元來尋址 當(dāng)一條無條件轉(zhuǎn)移指令中的地址表達(dá)式是一個(gè)段間(FAR)標(biāo)號或段間標(biāo)號加減一常量(必須在該標(biāo)號所在段內(nèi))時(shí),則該指令被匯編成一個(gè)段間直接

7、轉(zhuǎn)移指令代碼它轉(zhuǎn)移的目標(biāo)地址由存儲器尋址方式指定的內(nèi)存中的連續(xù)兩個(gè)字來決定,低地址的字取代IP,高地址的字取代CS功能IP=IP+DISPIP=Reg16 或 P=Mem16無條件轉(zhuǎn)移指令無條件轉(zhuǎn)移指令JMPlJMP指令轉(zhuǎn)移可以是短(short)轉(zhuǎn)移(偏移量在-128B,127B之內(nèi))、近(near)轉(zhuǎn)移(偏移量在-32KB,32KB之內(nèi))、遠(yuǎn)(far)轉(zhuǎn)移(在不同的代碼段之間轉(zhuǎn)移)。l短轉(zhuǎn)移和近轉(zhuǎn)移都是段內(nèi)轉(zhuǎn)移,JMP指令只將目標(biāo)指令位置處的偏移量賦值給指令指針寄存器IP,從而實(shí)現(xiàn)轉(zhuǎn)移功能l遠(yuǎn)轉(zhuǎn)移屬于段間轉(zhuǎn)移,JMP指令不僅會把目標(biāo)指令位置處的偏移量賦值給指令指針寄存器,同時(shí)還會把目標(biāo)指令所

8、處的代碼段的段地址賦值給當(dāng)前代碼段寄存器CS。 有條件轉(zhuǎn)移指令有條件轉(zhuǎn)移指令 l有條件轉(zhuǎn)移指令是一組及其重要的轉(zhuǎn)移指令,它根據(jù)標(biāo)志寄存器中的一個(gè)(或多個(gè))標(biāo)志位來決定是否需要轉(zhuǎn)移,這就為實(shí)現(xiàn)多功能程序提供了必要的手段 有條件轉(zhuǎn)移指令的格式和類型有條件轉(zhuǎn)移指令的格式和類型 指令格式 指令說明當(dāng)滿足條件而發(fā)生轉(zhuǎn)移的指令,稱為條件轉(zhuǎn)移指令。它們以某些標(biāo)志位或這些標(biāo)志位的邏輯運(yùn)算作為依據(jù),若滿足指令所規(guī)定條件,則程序轉(zhuǎn)移,否則順序執(zhí)行根據(jù)單個(gè)標(biāo)志位的條件轉(zhuǎn)移指令用于無符號數(shù)的條件轉(zhuǎn)移指令用于帶符號數(shù)的條件轉(zhuǎn)移指令(1)有進(jìn)位轉(zhuǎn)移(JC)或無進(jìn)位轉(zhuǎn)移(JNC)(2)等于/為零轉(zhuǎn)移(JE/JZ)或不等于/

9、非零轉(zhuǎn)移(JNZ)(3)負(fù)數(shù)轉(zhuǎn)移(JS)或正數(shù)轉(zhuǎn)移(JNS)(4)溢出轉(zhuǎn)移(JO)或不溢出轉(zhuǎn)移(JNO)(5)偶校驗(yàn)轉(zhuǎn)移(JP/JPE)或奇校驗(yàn)轉(zhuǎn)移(JNP/JPO)(6)寄存器CX為零轉(zhuǎn)移(JCXZ) (1)高于轉(zhuǎn)移(JA)/不低于且不等于轉(zhuǎn)移(JNBE)(2)高于或等于轉(zhuǎn)移(JAE)/不低于轉(zhuǎn)移(JNB)(3)低于轉(zhuǎn)移(JB)/不高于且不等于轉(zhuǎn)移(JNAE)(4)低于或等于轉(zhuǎn)移(JBE)/不高于轉(zhuǎn)移(JNA)(1)大于轉(zhuǎn)移(JG)/不小于且不等于轉(zhuǎn)移(JNLE)(2)大于或等于轉(zhuǎn)移(JGE)/不小于轉(zhuǎn)移(JNL)(3)小于轉(zhuǎn)移(JL)/不大于且不等于轉(zhuǎn)移(JNGE)(4)低于或等于轉(zhuǎn)移(J

10、LE)/不高于轉(zhuǎn)移(JNG)5.2.2 分支程序的結(jié)構(gòu)分支程序的結(jié)構(gòu)l分支程序結(jié)構(gòu)有兩種形式:雙分支結(jié)構(gòu)和多分支結(jié)構(gòu)。分支程序設(shè)計(jì)要點(diǎn)分支程序設(shè)計(jì)要點(diǎn) l(1)首先根據(jù)處理的問題用比較、測試、算術(shù)運(yùn)算、邏輯運(yùn)算等方式,使標(biāo)志寄存器產(chǎn)生相應(yīng)的標(biāo)志位。例如,比較兩個(gè)單元地址的高低、兩個(gè)數(shù)的大小,測試某個(gè)數(shù)據(jù)是正還是負(fù),測試數(shù)據(jù)的某位是“0”還是“1”等,將處理的結(jié)果反映在標(biāo)志寄存器的CF、ZF、SF、DF和OF位上。l(2)根據(jù)轉(zhuǎn)移條件選擇適當(dāng)?shù)霓D(zhuǎn)移指令。通常一條條件轉(zhuǎn)移指令只能產(chǎn)生兩路分支,因此要產(chǎn)生n路分支需n-1條條件轉(zhuǎn)移指令。l(3)各分支之間不能產(chǎn)生干擾,如果產(chǎn)生干擾,可用無條件轉(zhuǎn)移語句

11、進(jìn)行隔離。【例】【例】 設(shè)有單字節(jié)無符號數(shù)設(shè)有單字節(jié)無符號數(shù)X、Y、Z,若,若X+Y255,求,求X+Z;否則;否則求求X-Z,運(yùn)算結(jié)果放在,運(yùn)算結(jié)果放在F1中(中(X、Y、Z、F1均為字節(jié)變量名)。均為字節(jié)變量名)。l分析:這是一個(gè)雙分支結(jié)構(gòu)。因?yàn)閄、Y均為無符號數(shù),當(dāng)X+Y255時(shí)會產(chǎn)生進(jìn)位即CF=1,所以可以用進(jìn)位標(biāo)志來判斷 MOV AL,XMOV BL,ALADD AL,YJNC LET ;若無進(jìn)位 則轉(zhuǎn)LETADD BL,Z DONE: MOV F1,BLHLT LET: SUB BL,Z JMP DONEl【例】 已知符號函數(shù),假設(shè)任意給定x值,存放在內(nèi)存RS1單元中,求出函數(shù)y的

12、值,存放在內(nèi)存RS2單元中。lDATA SEGMENTlRS1 DB X ; 存放自變量存放自變量XlRS2 DB ? ; 函數(shù)函數(shù)Y值的存儲單元值的存儲單元lDATA ENDSlCODE SEGMENTlASSUME CS: CODE, DS: DATAlSTART: MOV AX, DATAl MOV DS, AXl MOV AL, RS1 ; ALXl CMP AL, 0 ; 將將X與與0比較比較l JGE BIG ; 若若X0BIGl MOV RS2, 0FFH ; 若若X0, (RS2)-1補(bǔ)補(bǔ)0FFHl JMP DONElBIG: JE EQUL ; 若若X0EQULl MOV R

13、S2, 1 ; 若若X0, (RS2)1l JMP DONElEQUL: MOV RS2, 0 ; 若若X0, (RS2)0lDONE: MOV AH, 4CHl INT 21HlCODE ENDSlEND START5.3 循環(huán)程序設(shè)計(jì)循環(huán)程序設(shè)計(jì)l在實(shí)際工作中,有時(shí)要求對某一問題進(jìn)行多次重復(fù)處理,而僅僅只是初始條件不同,這種計(jì)算過程稱為具有循環(huán)特征的,而循環(huán)程序設(shè)計(jì)是解決這類問題的一種行之有效的方法。循環(huán)程序是采用重復(fù)執(zhí)行某一段程序來實(shí)現(xiàn)要求完成計(jì)算的編程方法。5.3.1 循環(huán)指令循環(huán)指令l循環(huán)語句當(dāng)然可以用條件轉(zhuǎn)移指令來實(shí)現(xiàn),除此之外,在80 x86系統(tǒng)中還有專門的循環(huán)控制指令來簡化循環(huán)

14、程序的設(shè)計(jì)。循環(huán)控制指令包括重復(fù)控制指令和串操作指令。重復(fù)循環(huán)控制指令重復(fù)循環(huán)控制指令 指令名稱指令名稱指令功能指令功能LOOP指令將CX內(nèi)容減1,若CX不等于0,則循環(huán)至目標(biāo)地址處(即IP+DISP),否則順序執(zhí)行后續(xù)指令LOOPZ/LOOPE指令將CX內(nèi)容減1,若CX不等于0,且標(biāo)志位ZF=1時(shí),才循環(huán)至目標(biāo)地址處,否則順序執(zhí)行后續(xù)指令LOOPNZ/LOOPNE指令將CX內(nèi)容減1,若CX不等于0,且標(biāo)志位ZF=0時(shí),才循環(huán)至目標(biāo)地址處,否則順序執(zhí)行后續(xù)指令JCXZ指令這條指令是條件轉(zhuǎn)移指令,經(jīng)常用于重復(fù)循環(huán)控制注意:注意:在執(zhí)行此類重復(fù)控制指令前必須把重復(fù)次數(shù)送入寄存器CX中。串操作指令串

15、操作指令 l串操作指令能對存儲區(qū)中一塊(串)字節(jié)或字進(jìn)行操作,其塊的長度可達(dá)64KB。這些指令分別是:串復(fù)制指令MOVS、串取出指令LODS、串存儲指令STOS、串比較指令CMPS和串搜索(掃描)指令SCAS。 循環(huán)程序的結(jié)構(gòu)循環(huán)程序的結(jié)構(gòu) 循環(huán)程序一般包括以下5個(gè)部分:(1)初始化部分:)初始化部分:為循環(huán)做準(zhǔn)備工作,如設(shè)置地址指針、計(jì)數(shù)器及其他變量的初值等。(2)循環(huán)工作部分:)循環(huán)工作部分:它是循環(huán)程序的主體,用來完成循環(huán)的基本操作。(3)修改部分:)修改部分:為循環(huán)參數(shù)做必要的修改,如修改操作數(shù)地址、計(jì)數(shù)器,為下一次執(zhí)行循環(huán)體做好準(zhǔn)備。(4)控制部分:)控制部分:根據(jù)循環(huán)條件來判斷、控

16、制循環(huán)的繼續(xù)和終止。(5)結(jié)束部分:)結(jié)束部分:主要是對循環(huán)的結(jié)果進(jìn)行必要的處理,如將結(jié)果送入某一寄存器或內(nèi)存區(qū)域。循環(huán)程序的結(jié)構(gòu)循環(huán)程序的結(jié)構(gòu) 常見的循環(huán)程序結(jié)構(gòu)有兩種形式:“先處理后判斷”和“先判斷后處理” (BX)1 2 3 4把BX中的二進(jìn)制數(shù)以十六進(jìn)制的形式顯示在屏幕上。l D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 功能指令 mov ch, 4Rotate : mov cl, 4 rol bx, cl mov al, bl and al, 0fh add al, 30h ;0-9 ASCII cmp al, 3ah j

17、l printit add al, 7h ;A-F ASCII Printit : mov dl, al mov ah, 2 int 21h dec ch jnz rotate例例6設(shè)數(shù)組設(shè)數(shù)組X、Y中分別存有中分別存有10個(gè)字型數(shù)個(gè)字型數(shù)據(jù)。試實(shí)現(xiàn)以下計(jì)算并把結(jié)果存入據(jù)。試實(shí)現(xiàn)以下計(jì)算并把結(jié)果存入Z單元。單元。Z1X1+Y1 Z2X2+Y2 Z3X3-Y3Z4X4-Y4 Z5X5+Y5Z6X6-Y6 Z7X7-Y7 Z8X8-Y8Z9X9+Y9 Z10X10+Y10分析:雖然該例對分析:雖然該例對10個(gè)式子都存在取數(shù)、運(yùn)算和存數(shù)的操作,但操作個(gè)式子都存在取數(shù)、運(yùn)算和存數(shù)的操作,但操作符不同,

18、且無規(guī)律可循。設(shè)想按符不同,且無規(guī)律可循。設(shè)想按Z10、Z9Z1的計(jì)算順序把它們的的計(jì)算順序把它們的操作符自左至右排列起來,并把加用操作符自左至右排列起來,并把加用0表示,減用表示,減用1表示,則十個(gè)操表示,則十個(gè)操作符數(shù)字化后得到一串二進(jìn)制位作符數(shù)字化后得到一串二進(jìn)制位0011011100,把它放入一個(gè)字型,把它放入一個(gè)字型內(nèi)存變量中,其高內(nèi)存變量中,其高6位無意義,這種存儲單元一般被叫做邏輯尺。位無意義,這種存儲單元一般被叫做邏輯尺。計(jì)算時(shí)按照計(jì)算時(shí)按照Z1Z10順序,先求順序,先求Z1的值。每次把邏輯尺右移一位,的值。每次把邏輯尺右移一位,對移出位進(jìn)行判斷,若該位為對移出位進(jìn)行判斷,若該

19、位為0則加,為則加,為1則減。于是就可以用一個(gè)則減。于是就可以用一個(gè)分支加循環(huán)的混合程序?qū)崿F(xiàn)所要求的功能。分支加循環(huán)的混合程序?qū)崿F(xiàn)所要求的功能。在字型無序表中找出最大數(shù)和最小數(shù),在字型無序表中找出最大數(shù)和最小數(shù),并分別存入并分別存入MAX和和MIN單元。單元。l算法分析:把表中第一個(gè)元素分別作為最大數(shù)和最小數(shù),與下一個(gè)元素比較,若下一個(gè)元素比該元素大,則把下一個(gè)元素作為最大數(shù),繼續(xù)進(jìn)入下一輪比較;若下一個(gè)元素比該元素小,則把下一個(gè)元素作為最小數(shù),繼續(xù)進(jìn)入下一輪比較直至遍歷整個(gè)表,最后保留下來的兩個(gè)數(shù)就分別是表中的最大數(shù)和最小數(shù)。本例采用DO_UNTIL結(jié)構(gòu)實(shí)現(xiàn)。DATA SEGMENT BUF

20、 DW 500,30,56,77,999,67,433,5675DW 0,99993455,6578,32766,8DW 0,32560,45,889,5665,0,9CN DW ($-BUF)/2;元素個(gè)數(shù)MAX DW ?;存放最大數(shù)單元MIN DW ? ;存放最小數(shù)單元DATA ENDSCODE SEGMENTMAIN PROC FAR ASSUME CS:CODE,DS:DATA查表初始化查表初始化lPUSH DSMOV AX,0PUSH AXMOV AX,DATAMOV DS,AXLEA SI,BUFFER ;初始化地址指針MOV CX,CN ;元素個(gè)數(shù)MOV AX,SI ;取第一數(shù)M

21、OV MAX,AX ;初始化最大數(shù)MOV MIN,AX ;初始化最小數(shù)COMP:ADD SI,2 ;修改地址指針MOV AX,SI;取下一個(gè)數(shù)CMP AX,MAX;與當(dāng)前的最大數(shù)比較 JL NEXT;若小于轉(zhuǎn) MOV MAX,AX;若大于則把此數(shù)作為最大數(shù)保存 JMP LOPNEXT:CMP AX,MIN;與當(dāng)前的最小數(shù)比較 JG LOP;若大于轉(zhuǎn) MOV MIN,AX;若小于則把此數(shù)作為最小數(shù)保存LOP: LOOP COMP;決定循環(huán)繼續(xù)還是終止 RETMAIN ENDPCODE ENDSEND MAINYN初始化循環(huán)計(jì)數(shù)值初始化循環(huán)計(jì)數(shù)值i=0RULEi=1?Xi+YiXiYiYZi結(jié)果結(jié)

22、果i=i+1,循環(huán)次數(shù)減,循環(huán)次數(shù)減1N循環(huán)計(jì)數(shù)值循環(huán)計(jì)數(shù)值=0?例例6題解題解aDATA SEGMENTX DW 12H,34H,56H,78H,90HDW 0ABH,0CDH,0EFH,0F1H,023HY DW 9,8,7,6,5,4,3,2,1,0Z DW 10 DUP(?)RULE DW 0000000011011100B;邏輯尺DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATAMAIN PROC FAR MOV AX,DATA MOV DS,AX MOV BX,0;地址指針 MOV CX,10;循環(huán)次數(shù) MOV DX,RULE;邏輯尺例例6題解

23、題解bNEXT: MOV AX,XBX ;取X中的一個(gè)數(shù) SHR DX,1 ;邏輯尺右移一位 JC SUBS ;分支判斷并實(shí)現(xiàn)轉(zhuǎn)移ADD AX,YBX;兩數(shù)加JMP RESULTSUBS: SUB AX,YBX ;兩數(shù)減RESULT: MOV ZBX,AX;存結(jié)果 ADD BX,2 ;修改地址指針 LOOP NEXT MOV AX,4C00H INT 21HMAIN ENDPCODE ENDS END MAIN 討論: 這種設(shè)置邏輯尺的方法非常有用。例如要傳輸一批數(shù)據(jù)(定義為一個(gè)數(shù)組),該數(shù)組中含有多個(gè)0元素,為了節(jié)省存儲空間和傳輸時(shí)間,可以選用合適的數(shù)據(jù)結(jié)構(gòu)。比如可以使用壓縮數(shù)據(jù)及邏輯尺的方

24、法,把所有元素按下標(biāo)順序排列,并各用1個(gè)bit表示。設(shè)0元素用0表示,非0元素用1表示。存儲時(shí)只需保存非0元素(壓縮數(shù)組)和邏輯尺,當(dāng)進(jìn)行數(shù)據(jù)傳輸時(shí),若邏輯尺相應(yīng)位為1,則從壓縮數(shù)組中取到非0數(shù)據(jù)并傳送。若邏輯尺相應(yīng)位為0時(shí),只送一個(gè)標(biāo)志,在接收方直接生成數(shù)字0,這樣可以提高傳輸效率。5.4 子程序設(shè)計(jì)子程序設(shè)計(jì)l為了程序共享或模塊化設(shè)計(jì)的需要,把功能相對獨(dú)立的程序段單獨(dú)編寫和調(diào)試,作為一個(gè)相對獨(dú)立的模塊供程序使用,就形成子程序。l子程序可以實(shí)現(xiàn)源程序的模塊化,簡化源程序結(jié)構(gòu),提高編程效率。5.4.1 子程序概念子程序概念l子程序又稱過程,相當(dāng)于高級語言中的過程和函數(shù)。在一個(gè)程序的不同部分,往

25、往要用到“類似”的程序段,即這些程序段的功能和結(jié)構(gòu)形式都相同,只是某些變量賦值不同。此時(shí)就可以把這些程序段寫成子程序形式,以便需要時(shí)調(diào)用它。子程序偽指令子程序偽指令 l子程序的相關(guān)偽指令包括子程序的定義指令、調(diào)用指令和返回指令等 子程序定義指令子程序定義指令 子程序就是過程。過程定義偽指令的格式如下: PROC 類型屬性類型屬性 RET ENDP過程和主程序在同一代碼段時(shí),過程定義和調(diào)用格式如下:CODE SEGMENT SUBT PROC NEAR RET SUBT ENDP CALL SUBT CODE ENDS當(dāng)過程和主程序不在同一代碼段時(shí),過程定義和調(diào)用格式如下:CODE1 SEGME

26、NT SUBT PROC FAR RET SUBT ENDP CALL SUBTCODE1 ENDSCODE2 SEGMENT CALL SUBT CODE2 ENDS子程序調(diào)用指令子程序調(diào)用指令CALL lCALL指令用在主程序中,實(shí)現(xiàn)子程序的調(diào)用。子程序和主程序可以在同一個(gè)代碼段內(nèi),也可以在不同段內(nèi)。類似無條件轉(zhuǎn)移指令JMP,子程序調(diào)用指令CALL也可以分成段內(nèi)調(diào)用(近調(diào)用)和段間調(diào)用(遠(yuǎn)調(diào)用)lCALL目標(biāo)地址也可以采用直接尋址或間接尋址方式。但是子程序執(zhí)行結(jié)束后是要返回的,所以,CALL指令不僅要同JMP指令一樣改變CS:IP以實(shí)現(xiàn)轉(zhuǎn)移,而且還要保留下一條要執(zhí)行指令的地址,以便返回時(shí)重

27、新獲取它。保護(hù)CS:IP值的方法是壓入堆棧,獲取CS:IP值的方法就是彈出堆棧。 CALL 指令的指令的4種格式種格式(1)CALL LABEL。段內(nèi)調(diào)用,直接尋址:SPSP-2,SS:SPIP,IPIP+16位位移量。(2)CALL Reg16/Mem16。段內(nèi)調(diào)用,間接尋址:SPSP-2, SS:SPIP, IPReg16/Mem16。(3)CALL FAR PTR LABEL。段間調(diào)用,直接尋址:SPSP-2, SS:SPCS, SPSP-2,SS:SPIP,IPLABEL偏移地址,CSLABEL段地址。(4)CALL FAR PTR MEM。段間調(diào)用,間接尋址:SPSP-2, SS:S

28、PCS, SPSP-2,SS:SPIP,IPMEM,CSMEM+2。子程序返回指令子程序返回指令RET l子程序執(zhí)行完后,應(yīng)返回主程序中繼續(xù)執(zhí)行,這一功能由RET指令完成。要回到主程序,只需獲得離開主程序時(shí),由CALL指令保存于堆棧的指令地址即可。根據(jù)子程序與主程序是否同處于一個(gè)段內(nèi),返回指令分為段內(nèi)返回和段間返回。RET指令的指令的4種格式種格式 (1)RET。無參數(shù)段內(nèi)返回:IPSS:SP,SPSP+2。(2)RET Imm16。有參數(shù)段內(nèi)返回:IPSS:SP,SPSP+2,SPSP+Imm16。(3)RET。無參數(shù)段間返回:IPSS:SP,SPSP+2,CSSS:SP,SPSP+2。(4

29、)RET Imm16。有參數(shù)段間返回:IPSS:SP,SPSP+2,CSSS:SP,SPSP+2,SPSP+Imm16。子程序的調(diào)用子程序的調(diào)用 l對于一個(gè)子程序,應(yīng)該注意它的入口參數(shù)和出口參數(shù)。入口參數(shù)是由主程序傳給子程序的參數(shù),而出口參數(shù)是子程序運(yùn)算完傳給主程序的結(jié)果。另外,子程序所使用的寄存器和存儲單元往往需要保護(hù),以免影響返回后主程序的運(yùn)行。保護(hù)寄存器保護(hù)寄存器 l由于調(diào)用程序(即主程序)和子程序經(jīng)常是分別編制的,所以它們所使用的寄存器往往會發(fā)生沖突。如果主程序在調(diào)用子程序之前的某個(gè)寄存器內(nèi)容在從子程序返回后還有用,而子程序又恰好使用了同一個(gè)寄存器,這就破壞了該寄存器的原有內(nèi)容,因而會

30、造成程序運(yùn)行錯(cuò)誤,這是不允許的。為避免這種錯(cuò)誤的發(fā)生,在一進(jìn)入子程序后,就應(yīng)該把子程序所需要使用的寄存器內(nèi)容保存在堆棧中,而在退出子程序前把寄存器內(nèi)容恢復(fù)原狀。 寄存器保護(hù)實(shí)例寄存器保護(hù)實(shí)例SUBT PROC NEARPUSH AXPUSH BXPUSH CXPUSH DX POP DXPOP CXPOP BXPOP AXRETSUBT ENDP 一般說來,子程序中用到的寄存器是應(yīng)該保存的。但是,如果使用寄存器在主程序和子程序之間傳送參數(shù)的話,則這種寄存器就不一定需要保存,特別是用來向主程序回送結(jié)果的寄存器,就更不應(yīng)該因保存和恢復(fù)寄存器而破壞了應(yīng)該向主程序傳送的信息 。設(shè)計(jì)子程序應(yīng)注意的問題設(shè)

31、計(jì)子程序應(yīng)注意的問題1子程序說明子程序說明為便于引用,子程序應(yīng)在開頭對其功能、調(diào)用參數(shù)和為便于引用,子程序應(yīng)在開頭對其功能、調(diào)用參數(shù)和返回參數(shù)等予以說明,例如參數(shù)的類型、格式及存放返回參數(shù)等予以說明,例如參數(shù)的類型、格式及存放位置等。位置等。2寄存器的保存與恢復(fù)寄存器的保存與恢復(fù)為了保證調(diào)用程序的寄存器內(nèi)容不被破壞,應(yīng)在子程為了保證調(diào)用程序的寄存器內(nèi)容不被破壞,應(yīng)在子程序開頭保存它要用到的寄存器內(nèi)容,返回前再恢復(fù)它序開頭保存它要用到的寄存器內(nèi)容,返回前再恢復(fù)它們。通常用們。通常用PUSH指令保存指令保存,用用POP恢復(fù)。進(jìn)出堆棧的恢復(fù)。進(jìn)出堆棧的順序相反。順序相反。設(shè)計(jì)子程序應(yīng)注意的問題設(shè)計(jì)子

32、程序應(yīng)注意的問題3密切注意堆棧狀態(tài)密切注意堆棧狀態(tài) 在設(shè)計(jì)含有子程序的源程序時(shí),要密切注意一切與在設(shè)計(jì)含有子程序的源程序時(shí),要密切注意一切與堆棧有關(guān)的操作。例如堆棧有關(guān)的操作。例如 CALL調(diào)用類型和子程序定義類型的一致性調(diào)用類型和子程序定義類型的一致性;PUSH和和POP指令的匹配;通過堆棧傳遞參數(shù)時(shí)子程序返回指令的匹配;通過堆棧傳遞參數(shù)時(shí)子程序返回使用使用RET n指令指令等;以確保堆棧平衡,否則后果不可等;以確保堆棧平衡,否則后果不可預(yù)料。預(yù)料。子程序參數(shù)傳遞子程序參數(shù)傳遞可以通過給子程序傳遞參數(shù)使其更通用??梢酝ㄟ^給子程序傳遞參數(shù)使其更通用。入口參數(shù)入口參數(shù)(輸入?yún)?shù)):主程序(輸入?yún)?/p>

33、數(shù)):主程序 提供給提供給 子程序子程序出口參數(shù)出口參數(shù)(輸出參數(shù)):子程序(輸出參數(shù)):子程序 返回給返回給 主程序主程序 數(shù)據(jù)本身數(shù)據(jù)本身( (傳值傳值) ) 數(shù)據(jù)的地址數(shù)據(jù)的地址( (傳址傳址) ) 寄存器寄存器 地址表地址表 堆棧堆棧通過寄存器傳遞單個(gè)變量或者地址;通過寄存器傳遞單個(gè)變量或者地址;通過地址表傳遞多個(gè)參數(shù)地址(存儲單元);通過地址表傳遞多個(gè)參數(shù)地址(存儲單元);通過堆棧傳遞參數(shù)或參數(shù)地址。通過堆棧傳遞參數(shù)或參數(shù)地址。這種傳遞方式使用方便,適用于參數(shù)較少的情況。這種傳遞方式使用方便,適用于參數(shù)較少的情況。把參數(shù)存于約定的寄存器中,可以傳值,也可以傳地址。把參數(shù)存于約定的寄存

34、器中,可以傳值,也可以傳地址。子程序?qū)в谐隹趨?shù)的寄存器不能保護(hù)和恢復(fù)(主程序視具體子程序?qū)в谐隹趨?shù)的寄存器不能保護(hù)和恢復(fù)(主程序視具體情況進(jìn)行保護(hù))。情況進(jìn)行保護(hù))。子程序?qū)в腥肟趨?shù)的寄存器可以保護(hù),也可以不保護(hù);但最子程序?qū)в腥肟趨?shù)的寄存器可以保護(hù),也可以不保護(hù);但最好統(tǒng)一。好統(tǒng)一。例例 把把BX中的二進(jìn)制數(shù)轉(zhuǎn)換成十進(jìn)制并顯示在屏幕上。中的二進(jìn)制數(shù)轉(zhuǎn)換成十進(jìn)制并顯示在屏幕上。分析:本例采用從高到低逐個(gè)除以十進(jìn)制位權(quán)的方法。分析:本例采用從高到低逐個(gè)除以十進(jìn)制位權(quán)的方法。題解:題解:MAINPROCFAR。MOV BX,162EHCALL TERN ;轉(zhuǎn)換并顯示轉(zhuǎn)換并顯示MOV

35、 AX,4C00H ;安全退出程序安全退出程序 INT 21HMAINENDP1通過寄存器傳遞參數(shù)通過寄存器傳遞參數(shù)TERN PROC ;二二十并顯示。十并顯示。 MOV CX,10000CALL DEC_DIV;轉(zhuǎn)換萬位數(shù)轉(zhuǎn)換萬位數(shù) MOV CX,1000CALL DEC_DIV;轉(zhuǎn)換千位數(shù)轉(zhuǎn)換千位數(shù) MOV CX,100CALL DEC_DIV;轉(zhuǎn)換百位數(shù)轉(zhuǎn)換百位數(shù) MOV CX,10CALL DEC_DIV;轉(zhuǎn)換十位數(shù)轉(zhuǎn)換十位數(shù) MOV CX,1CALL DEC_DIV;轉(zhuǎn)換個(gè)位數(shù)轉(zhuǎn)換個(gè)位數(shù)RETTERN ENDP例解bDEC_DIVPROC;CX中為十進(jìn)制的位權(quán)中為十進(jìn)制的位權(quán)MOV

36、AX,BXMOV DX,0 DIV CX;商為轉(zhuǎn)換后的一位十進(jìn)制數(shù)商為轉(zhuǎn)換后的一位十進(jìn)制數(shù)MOV BX,DX ;保留余數(shù)輸出,做下次轉(zhuǎn)換保留余數(shù)輸出,做下次轉(zhuǎn)換MOV DL,AL ADD DL,30H;轉(zhuǎn)換成轉(zhuǎn)換成ASCII碼顯示碼顯示 MOV AH,2INT 21H RETDEC_DIVENDPCODE ENDS END MAIN例解c例實(shí)現(xiàn)數(shù)組求和功能。要求數(shù)組求和(不考慮溢出例實(shí)現(xiàn)數(shù)組求和功能。要求數(shù)組求和(不考慮溢出情況)由子程序?qū)崿F(xiàn),其數(shù)組元素及結(jié)果均為字型數(shù)情況)由子程序?qū)崿F(xiàn),其數(shù)組元素及結(jié)果均為字型數(shù)據(jù)。據(jù)。例例6.2 解解a:DATA SEGMENTARY DW 1,2,3,4

37、,5,6,7,8,9,10COUNT DW ($-ARY)/2;數(shù)組元素個(gè)數(shù)數(shù)組元素個(gè)數(shù)SUM DW ?;數(shù)組和的地址數(shù)組和的地址DATAENDS2若調(diào)用程序和子程序在同模塊中,子程序可以若調(diào)用程序和子程序在同模塊中,子程序可以直接訪問模塊中的變量直接訪問模塊中的變量CODE1 SEGMENTMAIN PROC FAR ASSUME CS:CODE1,DS:DATA MOV AX,DATA MOV DS,AX CALL FAR PTR ARY_SUMMOV AX,4C00HINT 21HMAIN ENDPCODE1 ENDS例例6.2 解解bCODE2 SEGMENT ASSUME CS:CO

38、DE2ARY_SUM PROC FAR;數(shù)組求和子程序數(shù)組求和子程序 PUSH AX;保存寄存器保存寄存器 PUSH CX PUSH SI LEA SI,ARY;取數(shù)組起始地址取數(shù)組起始地址 MOV CX,COUNT;取元素個(gè)數(shù)取元素個(gè)數(shù) XOR AX,AX;清清0累加器累加器NEXT: ADD AX,SI;累加和累加和 ADD SI,2;修改地址指針修改地址指針 LOOP NEXT MOV SUM,AX;存和存和 ;恢復(fù)寄存器恢復(fù)寄存器RET ARY_SUM ENDP。例例6.2 解解c3通過地址表傳遞參數(shù)地址通過地址表傳遞參數(shù)地址 適用于參數(shù)較多的情況。方法是先建立一適用于參數(shù)較多的情況。

39、方法是先建立一個(gè)地址表,該表由參數(shù)地址構(gòu)成。然后把表個(gè)地址表,該表由參數(shù)地址構(gòu)成。然后把表的首地址通過寄存器或堆棧傳遞給子程序。的首地址通過寄存器或堆棧傳遞給子程序。 例例 編寫一個(gè)數(shù)組求和子程序,其數(shù)組元編寫一個(gè)數(shù)組求和子程序,其數(shù)組元素及結(jié)果均為字型數(shù)據(jù)。另定義兩個(gè)數(shù)組,素及結(jié)果均為字型數(shù)據(jù)。另定義兩個(gè)數(shù)組,并編寫一個(gè)主程序,通過調(diào)用數(shù)組求和子程并編寫一個(gè)主程序,通過調(diào)用數(shù)組求和子程序分別求出兩個(gè)數(shù)組的和。序分別求出兩個(gè)數(shù)組的和。分析:雖然主、子程序在同模塊中,但由于分析:雖然主、子程序在同模塊中,但由于在一個(gè)程序中要分別求出兩個(gè)數(shù)組的和,因在一個(gè)程序中要分別求出兩個(gè)數(shù)組的和,因此子程序不

40、能直接引用數(shù)組變量名。本例用此子程序不能直接引用數(shù)組變量名。本例用數(shù)組首地址數(shù)組首地址、元素個(gè)數(shù)的地址、和數(shù)地址元素個(gè)數(shù)的地址、和數(shù)地址構(gòu)構(gòu)成地址表,通過地址表傳送這些參數(shù)的地址,成地址表,通過地址表傳送這些參數(shù)的地址,以便子程序能夠訪問到所需參數(shù)以便子程序能夠訪問到所需參數(shù)。數(shù)組的首地址數(shù)組長度存放單元的地址數(shù)組累加和存放單元的地址地址表地址表解解aDATA SEGMENTARY DW 1,2,3,4,5,6,7,8,9,10;數(shù)組數(shù)組1COUNT DW ($-ARY)/2;數(shù)組數(shù)組1的元素個(gè)數(shù)的元素個(gè)數(shù)SUM DW ?;數(shù)組數(shù)組1的和地址的和地址NUM DW 10,20,30,40,50;

41、數(shù)組數(shù)組2CT DW ($-NUM)/2;數(shù)組數(shù)組2的元素個(gè)數(shù)的元素個(gè)數(shù)TOTAL DW ?;數(shù)組數(shù)組2的和地址的和地址TABLE DW 3 DUP(?);地址表地址表DATA ENDSCODE1 SEGMENTMAINPROC FAR ASSUME CS:CODE1,DS:DATA。 MOV TABLE,OFFSET ARY ;構(gòu)造數(shù)組構(gòu)造數(shù)組1的地址表的地址表 MOV TABLE+2,OFFSET COUNT MOV TABLE+4,OFFSET SUM LEA BX,TABLE;傳遞地址表首地址傳遞地址表首地址 CALL FAR PTR ARY_SUM ;段間調(diào)用數(shù)組求和子段間調(diào)用數(shù)組求

42、和子程序程序MOV TABLE,OFFSET NUM;構(gòu)造數(shù)組構(gòu)造數(shù)組2的地址表的地址表MOV TABLE+2,OFFSET CTMOV TABLE+4,OFFSET TOTALLEA BX,TABLE ;傳遞地址表的首地址傳遞地址表的首地址CALL FAR PTR ARY_SUM。MAIN ENDPCODE1 ENDS解解bCODE2 SEGMENT ASSUME CS:CODE2ARY_SUM PROC FAR;數(shù)組求和子程序數(shù)組求和子程序 PUSH AX;保存寄存器保存寄存器 PUSH CX PUSH SI PUSH DI MOV SI,BX;取數(shù)組起始地址取數(shù)組起始地址 MOV DI,

43、BX+2;取元素個(gè)數(shù)地址取元素個(gè)數(shù)地址 MOV CX,DI;取元素個(gè)數(shù)取元素個(gè)數(shù) MOV DI,BX+4;取結(jié)果地址取結(jié)果地址 XOR AX,AX;清清0累加器累加器解解cNEXT:ADD AX,SI;累加累加 ADD SI,2;修改地址指針修改地址指針 LOOP NEXT MOV DI,AX;存和存和 POP DI;恢復(fù)寄存器恢復(fù)寄存器 POP SI POP CX POP AX RET ARY_SUM ENDPCODE2 ENDS END MAIN解解d這種方式適用于參數(shù)較多,或子程序有多層嵌套、這種方式適用于參數(shù)較多,或子程序有多層嵌套、遞歸調(diào)用的情況。遞歸調(diào)用的情況。實(shí)現(xiàn)步驟:實(shí)現(xiàn)步驟:

44、p主程序把主程序把參數(shù)參數(shù)或或參數(shù)地址參數(shù)地址壓入堆棧;壓入堆棧;p子程序使用堆棧中的參數(shù)或通過棧中參數(shù)地址取子程序使用堆棧中的參數(shù)或通過棧中參數(shù)地址取到參數(shù);到參數(shù);p子程序返回時(shí)使用子程序返回時(shí)使用RET n指令調(diào)整指令調(diào)整SP指針,以指針,以便刪除堆棧中已用過的參數(shù),保持堆棧平衡,保便刪除堆棧中已用過的參數(shù),保持堆棧平衡,保證程序的正確返回。證程序的正確返回。4通過堆棧傳遞參數(shù)或參數(shù)地址通過堆棧傳遞參數(shù)或參數(shù)地址例題解a:STACK SEGMENT STACK STKDW 16 DUP(?)STACK ENDSDATA SEGMENTARY DW 1,2,3,4,5,6,7,8,9,10

45、COUNT DW ($-ARY)/2SUM DW ?DATA ENDSCODE1 SEGMENTMAIN PROC FAR ASSUME CS:CODE1,DS:DATA,SS:STACK例例.完成數(shù)組求和功能,求和由子程序?qū)崿F(xiàn),完成數(shù)組求和功能,求和由子程序?qū)崿F(xiàn),要求通過堆棧傳遞參數(shù)地址。要求通過堆棧傳遞參數(shù)地址。MOV AX,DATA MOV DS,AXMOV AX,STACKMOV SS,AXLEA BX,ARY PUSH BX;壓入數(shù)組起始地址 LEA BX,COUNT PUSH BX;壓入元素個(gè)數(shù)地址 LEA BX,SUM PUSH BX;壓入和地址 CALL FAR PTR ARY

46、_SUM ;調(diào)用求和子程序 INT 20H;例題解例題解bCODE2 SEGMENT ASSUME CS:CODE2ARY_SUM PROC FAR;數(shù)組求和子程序數(shù)組求和子程序 PUSH BP;保存保存BP值值 MOV BP,SP ;BP是堆棧數(shù)據(jù)的地址指針是堆棧數(shù)據(jù)的地址指針 PUSH AX;保存寄存器內(nèi)容保存寄存器內(nèi)容 PUSH CX; PUSH SI; PUSH DI; MOV SI,BP+10;得到數(shù)組起始地址得到數(shù)組起始地址 MOV DI,BP+8;得到元素個(gè)數(shù)地址得到元素個(gè)數(shù)地址 MOV CX,DI;得到元素個(gè)數(shù)得到元素個(gè)數(shù) MOV DI,BP+6;得到和地址得到和地址 XOR

47、AX,AX例題解cNEXT: ADD AX,SI ;累加累加 ADD SI,2;修改地址指針修改地址指針 LOOP NEXT MOV DI,AX;存和存和 POP DI;恢復(fù)寄存器內(nèi)容恢復(fù)寄存器內(nèi)容 POP SI; POP CX; POP AX; POP BP; RET 6;返回并調(diào)整返回并調(diào)整SP指針指針ARY_SUM ENDPCODE2 ENDS END MAIN例題解d本例通過本例通過BP訪問堆棧中的參數(shù)。訪問堆棧中的參數(shù)。程序的堆棧變化情況參見圖程序的堆棧變化情況參見圖a,指示了程序指示了程序中所有入棧操作對堆棧的影響隨入棧數(shù)據(jù)的增中所有入棧操作對堆棧的影響隨入棧數(shù)據(jù)的增加加,SP的值

48、不斷減小,堆??捎每臻g也隨之減的值不斷減小,堆棧可用空間也隨之減少。少。圖圖b為已從子程序返回、而主程序?yàn)橐褟淖映绦蚍祷?、而主程序RET指指令執(zhí)行前的堆棧狀態(tài),其中的灰色部分表示執(zhí)令執(zhí)行前的堆棧狀態(tài),其中的灰色部分表示執(zhí)行語句行語句時(shí)已彈出的數(shù)據(jù)。時(shí)已彈出的數(shù)據(jù)。 從以上分析可以看出,通過堆棧傳遞參數(shù)從以上分析可以看出,通過堆棧傳遞參數(shù)時(shí)子程序的返回指令必須是時(shí)子程序的返回指令必須是RET N形式,當(dāng)堆形式,當(dāng)堆棧操作是棧操作是16位時(shí)位時(shí)N值應(yīng)該是壓入堆棧的參數(shù)個(gè)值應(yīng)該是壓入堆棧的參數(shù)個(gè)數(shù)的數(shù)的2倍倍,只有這樣保證程序的正常運(yùn)行。只有這樣保證程序的正常運(yùn)行。用結(jié)構(gòu)形式訪問堆棧中的參數(shù),這種方

49、法用結(jié)構(gòu)形式訪問堆棧中的參數(shù),這種方法更簡便及規(guī)范化。更簡便及規(guī)范化。利用堆棧傳遞秋和子程序需要的參數(shù)利用堆棧傳遞秋和子程序需要的參數(shù)(DI)(SI)(CX)(AX)(BP)數(shù)組長度存放單元的地址數(shù)組的起始地址堆棧操作前棧頂數(shù)組和數(shù)存放單元的地址子程序返回地址CS子程序返回地址IP+2 -10+4 -8+6 -6+8 -4+10 -2(sp) (BP) (SP)-12(BP) (SP)-12返回返回語句語句執(zhí)行后堆棧狀態(tài)執(zhí)行后堆棧狀態(tài)語句語句執(zhí)行后堆棧狀態(tài)執(zhí)行后堆棧狀態(tài)語句語句執(zhí)行后堆棧狀態(tài)執(zhí)行后堆棧狀態(tài)語句語句執(zhí)行后堆棧狀態(tài)執(zhí)行后堆棧狀態(tài)語句語句執(zhí)行后堆棧狀態(tài)執(zhí)行后堆棧狀態(tài)語句語句執(zhí)行后堆棧

50、狀態(tài)執(zhí)行后堆棧狀態(tài)語句語句執(zhí)行后堆棧狀態(tài)執(zhí)行后堆棧狀態(tài)語句語句執(zhí)行后堆棧狀態(tài)執(zhí)行后堆棧狀態(tài)語句語句執(zhí)行后堆棧狀態(tài)執(zhí)行后堆棧狀態(tài)語句語句執(zhí)行后堆棧狀態(tài)執(zhí)行后堆棧狀態(tài)語句語句執(zhí)行后堆棧狀態(tài)執(zhí)行后堆棧狀態(tài)SSSSSPSPBPBPDIDI值值SISI值值CXCX值值A(chǔ)XAX值值BPBP值值IPIP值值CSCS值值SUMSUM的地址的地址COUNTCOUNT地址地址ARYARY首地址首地址初始棧頂初始棧頂PSPPSP段基址段基址圖a 程序中所有入棧操作對堆棧的影響返回返回SPSP語句語句執(zhí)行后堆棧狀態(tài)執(zhí)行后堆棧狀態(tài)SSSSDIDI值值SISI值值CXCX值值A(chǔ)XAX值值BPBP值值IPIP值值CSCS值

51、值SUMSUM的地址的地址COUNTCOUNT地址地址ARYARY首地址首地址初始棧頂初始棧頂PSPPSP段基址段基址圖b 程序中主程序的RET執(zhí)行前堆棧狀態(tài) 例完成數(shù)組求和功能,其中求和由子程序例完成數(shù)組求和功能,其中求和由子程序?qū)崿F(xiàn),要求使用結(jié)構(gòu)訪問堆棧中的參數(shù)。實(shí)現(xiàn),要求使用結(jié)構(gòu)訪問堆棧中的參數(shù)。 圖圖c給出了堆棧及給出了堆棧及結(jié)構(gòu)數(shù)據(jù)定義結(jié)構(gòu)數(shù)據(jù)定義。注意這些結(jié)。注意這些結(jié)構(gòu)字段的順序?yàn)槠渲祲喝氲哪嫘?。?shí)際上構(gòu)字段的順序?yàn)槠渲祲喝氲哪嫘?。?shí)際上,它它只只是給圖是給圖a中由主程序壓入的數(shù)據(jù)、返回地址及子中由主程序壓入的數(shù)據(jù)、返回地址及子程序壓入的程序壓入的BP值起了個(gè)名字而已,值起了個(gè)名

52、字而已,而字段值的而字段值的預(yù)置是通過預(yù)置是通過PUSH和和CALL指令實(shí)現(xiàn)的。當(dāng)子程指令實(shí)現(xiàn)的。當(dāng)子程序用到堆棧中的參數(shù)時(shí),只需使用序用到堆棧中的參數(shù)時(shí),只需使用BP作為基地作為基地址、通過結(jié)構(gòu)字段名訪問就可以了。編碼見程序。址、通過結(jié)構(gòu)字段名訪問就可以了。編碼見程序。使用堆棧傳遞結(jié)構(gòu)數(shù)據(jù)返回返回SSSSSPSPBPBPDIDI值值堆棧數(shù)據(jù)SISI值值結(jié)構(gòu)字段名CXCX值值A(chǔ)XAX值值BPBP值值SAVE_BPIPIP值值SAVE_CS_IPCSCS值值SUMSUM的地址的地址SUM_ADDRCOUNTCOUNT地址地址COUNT_ADDRARYARY首地址首地址ARY_ADDR0 0PSP

53、PSP段基址段基址結(jié)構(gòu)結(jié)構(gòu)圖c 程序的堆棧及結(jié)構(gòu)數(shù)據(jù)示意圖程序源碼程序源碼STACK SEGMENT STACK STKDW 16 DUP(?)TOPEQU $STACK ENDSDATA SEGMENTARY DW 1,2,3,4,5,6,7,8,9,10COUNT DW ($-ARY)/2SUM DW ?DATA ENDSCODE1 SEGMENTASSUME CS:CODE1,DS:DATA,SS:STACKMAINPROCFARMOV AX,DATAMOV DS,AX程序源碼程序源碼aMOV AX,STAKMOV SS,AXMOV SP,TOP;設(shè)置棧頂指針設(shè)置棧頂指針LEA BX,A

54、RY PUSH BX;壓入數(shù)組起始地址壓入數(shù)組起始地址 LEA BX,COUNT PUSH BX;壓入元素個(gè)數(shù)地址壓入元素個(gè)數(shù)地址 LEA BX,SUM PUSH BX;壓入和地址壓入和地址 CALL FAR PTR ARY_SUMMOV AX,4C00HINT 21HMAIN ENDPCODE1 ENDS CODE2 SEGMENT ASSUME CS:CODE2STACK_STRC STRUC;定義結(jié)構(gòu)定義結(jié)構(gòu)SAVE_BP DW ?SAVE_CS_IP DW 2 DUP(?)SUM_ADDR DW ?COUNT_ADDR DW ?ARY_ADDR DW ?STACK_STRC ENDS

55、程序源碼程序源碼bARY_SUMPROC FAR;數(shù)組求和子程序數(shù)組求和子程序 PUSH BP;保存保存BP值,值, MOV BP,SP;(BP) 結(jié)構(gòu)數(shù)據(jù)指針結(jié)構(gòu)數(shù)據(jù)指針PUSH AX PUSH CX PUSH SI PUSH DI MOV SI,BP.ARY_ADDR;取數(shù)組首地址取數(shù)組首地址 MOV DI,BP.COUNT_ADDR;取數(shù)組長度;取數(shù)組長度 MOV CX,DI MOV DI,BP.SUM_ADDR;取數(shù)組和數(shù)地址取數(shù)組和數(shù)地址程序源程序源cXOR AX,AXNEXT: ADD AX,SI;累加累加 ADD SI,2;修改地址指針修改地址指針 LOOP NEXT MOV D

56、I,AX;存和存和 POP DI POP SI POP CX POP AX POP BP RET 6;返回并調(diào)整返回并調(diào)整SP指針指針ARY_SUM ENDP。程序源程序源d1分析:由于題目要求從外設(shè)輸入輸出數(shù)分析:由于題目要求從外設(shè)輸入輸出數(shù)據(jù),而在內(nèi)存中用二進(jìn)制數(shù)形式實(shí)現(xiàn)乘法,所以涉據(jù),而在內(nèi)存中用二進(jìn)制數(shù)形式實(shí)現(xiàn)乘法,所以涉及到代碼轉(zhuǎn)換問題。步驟如下:及到代碼轉(zhuǎn)換問題。步驟如下:l從鍵盤輸入兩個(gè)十進(jìn)制乘數(shù)(從鍵盤輸入兩個(gè)十進(jìn)制乘數(shù)(ASCII碼)碼)l分別轉(zhuǎn)換成二進(jìn)制形式分別轉(zhuǎn)換成二進(jìn)制形式l二進(jìn)制數(shù)乘二進(jìn)制數(shù)乘l把二進(jìn)制乘積轉(zhuǎn)換成十進(jìn)制數(shù)的把二進(jìn)制乘積轉(zhuǎn)換成十進(jìn)制數(shù)的ASCII碼形式碼

57、形式l輸出到屏幕。輸出到屏幕。例例. 編寫兩個(gè)四位無符號十進(jìn)制數(shù)乘法程序。要求:乘數(shù)編寫兩個(gè)四位無符號十進(jìn)制數(shù)乘法程序。要求:乘數(shù)從鍵盤輸入;二進(jìn)制乘;用十進(jìn)制數(shù)形式顯示乘積。從鍵盤輸入;二進(jìn)制乘;用十進(jìn)制數(shù)形式顯示乘積。本例中的輸入、輸出、十進(jìn)制到二進(jìn)制的本例中的輸入、輸出、十進(jìn)制到二進(jìn)制的轉(zhuǎn)換、以及二進(jìn)制到十進(jìn)制的轉(zhuǎn)換均采用子程序轉(zhuǎn)換、以及二進(jìn)制到十進(jìn)制的轉(zhuǎn)換均采用子程序形式實(shí)現(xiàn)。形式實(shí)現(xiàn)。* 十十二轉(zhuǎn)換算法:二轉(zhuǎn)換算法:Y=Y*10+Xi(Y的初始值為的初始值為0,i =n,n-1,0)ASC_BIN是實(shí)現(xiàn)四位十進(jìn)制數(shù)轉(zhuǎn)換成二進(jìn)是實(shí)現(xiàn)四位十進(jìn)制數(shù)轉(zhuǎn)換成二進(jìn)制數(shù)的子程序。程序中制數(shù)的子程序

58、。程序中Y值在值在AX中,中,i值由值由CL控控制。制。2設(shè)計(jì):設(shè)計(jì): 十十二轉(zhuǎn)換算法二轉(zhuǎn)換算法除除10取余法。即用取余法。即用32位的二進(jìn)制乘積作為被位的二進(jìn)制乘積作為被除數(shù),除數(shù),10作為除數(shù),每次除后所得到的余數(shù)就是作為除數(shù),每次除后所得到的余數(shù)就是本位的十進(jìn)制數(shù)本位的十進(jìn)制數(shù),并把它轉(zhuǎn)換成并把它轉(zhuǎn)換成ASCII碼存放在輸碼存放在輸出緩沖區(qū)的相應(yīng)位置,直到整個(gè)轉(zhuǎn)換結(jié)束,最后出緩沖區(qū)的相應(yīng)位置,直到整個(gè)轉(zhuǎn)換結(jié)束,最后輸出。輸出。實(shí)現(xiàn)該算法的子程序是BIN_ASC??紤]到32位的被除數(shù)除以10很容易產(chǎn)生超過16位的商,從而產(chǎn)生除法錯(cuò)中斷無法得到正確結(jié)果,因此需要采用一種避免產(chǎn)生除法錯(cuò)中斷的技

59、術(shù)。本例采用的方法是把32位被除數(shù)擴(kuò)展成48位,其中最高16位為0,然后進(jìn)行除法運(yùn)算。示意圖如下:* 二十轉(zhuǎn)換算法: * 二十轉(zhuǎn)換算法: 全全0 0CR EQU 0DHLF EQU 0AHSTACKSG SEGMENT STACK S DW 64 DUP(ST)STACKSG ENDS3編碼編碼DATA SEGMENTPROMPT1 DBCR,LF,INPUTNUM1:$PROMPT2 DBCR,LF,INPUTNUM2:$ ASCIN1 DB5 , ? , 5 DUP(?)ASCIN2 DB5 , ? , 5 DUP(?)BIN1 DW?;乘數(shù)乘數(shù)1二進(jìn)制值二進(jìn)制值BIN2 DW?;乘數(shù)乘數(shù)

60、2二進(jìn)制值二進(jìn)制值RSLTHI DW0;32位二進(jìn)制乘積的高位二進(jìn)制乘積的高16位位RSLTLO DW0;32位二進(jìn)制乘積的低位二進(jìn)制乘積的低16位位ASCOUT0 DBCR,LF,RESULT:ASC_OUT DB10DUP(0),$DATA ENDS數(shù)據(jù)段定義數(shù)據(jù)段定義CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACKSGMAIN PROC FAR MOV AX,DATA MOV DS,AXMOV AX, STACKSG MOV SS,AX LEA DX,PROMPT1 CALL DISP;顯示提示信息顯示提示信息1 LEA DX,ASCIN1 CAL

溫馨提示

  • 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

提交評論