基本匯編語言程序設(shè)計_第1頁
基本匯編語言程序設(shè)計_第2頁
基本匯編語言程序設(shè)計_第3頁
基本匯編語言程序設(shè)計_第4頁
基本匯編語言程序設(shè)計_第5頁
已閱讀5頁,還剩92頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、第四章基本匯編語言程序設(shè)計 1第四章基本匯編語言程序設(shè)計第四章 基本匯編語言程序設(shè)計4.1順序程序設(shè)計4.2 分支程序設(shè)計4.3 循環(huán)程序設(shè)計4.4 子程序設(shè)計4.4.1 過程定義偽指令4.4.2 子程序的參數(shù)傳遞4.4.3 子程序的嵌套、遞歸與重入4.4.4 子程序的應(yīng)用 本章要點及習(xí)題分析24.1順序程序設(shè)計(e)4.1順序程序設(shè)計指令按程序中的書寫順序逐條執(zhí)行,稱為順序程序。除非編程解決非常簡單的問題,順序程序并不多見,但是順序程序往往是復(fù)雜程序結(jié)構(gòu)的一部分,如分支結(jié)構(gòu)的一個分支,循環(huán)結(jié)構(gòu)的循環(huán)體等。返回第四章3例4.1例4.1:設(shè)有3個字變量x,y和z,求出三者之和,結(jié)果存入字變量w。

2、.model small .startup.stack mov ax,x.data add ax,yXdw 5 add ax,zYdw 6 mov w,axZdw 7 .exit 0Wdw ? end.code4例4.2/1例4.2 設(shè)有一個64位數(shù)據(jù),將它整個左移8位。123456788765432100qvar0qvar1qvar2qvar3qvar4qvar5qvar6qvar75例4.2/2 .model small .stack .dataQvar dq 1234567887654321h.codemov al,byte ptr qvar6mov byte ptr qvar7,alm

3、ov al,byte ptr qvar5mov byte ptr qvar6,almov al,byte ptr qvar4mov byte ptr qvar5,almov al,byte ptr qvar3mov byte ptr qvar4,al6例4.2/3 mov al,byte ptr qvar2mov byte ptr qvar3,almov al,byte ptr qvar1mov byte ptr qvar2,almov al,byte ptr qvar0mov byte ptr qvar1,almov byte ptr qvar0,012 34 56 78 87 65 43

4、21h34 56 78 87 65 43 21 00h(移位前)(移位后)返回第四章74.2分支程序設(shè)計4.2 分支程序設(shè)計條件轉(zhuǎn)移指令Jcc和無條件轉(zhuǎn)移指令JMP用于實現(xiàn)程序的分支結(jié)構(gòu),JMP不測試條件,Jcc可根據(jù)條件是否成立決定轉(zhuǎn)移到指定位置或不轉(zhuǎn)移而順序執(zhí)行后續(xù)指令。由于Jcc不支持條件表達式,而是以當(dāng)前標(biāo)志位的狀態(tài)為條件,故Jcc之前一定要安排設(shè)置標(biāo)志位的指令,如加減法、比較、測試等指令?;痉种ь愋头譃閱畏种Ш碗p分支。8單分支1. 單分支類型 對同一個問題,根據(jù)選擇的條件不同,單分支結(jié)構(gòu)的流程圖有兩種畫法,對應(yīng)的程序也有兩種編法。如計算AX中的有符號數(shù)的絕對值。9單分支 cmp a

5、x,0 jge noneg neg axNoneg: mov result,ax cmp ax,0(教材有誤) jnge yesneg jmp doneyesneg: neg axDone: mov result,axAX0 ?求補指令YN保存結(jié)果AX0?求補指令YN保存結(jié)果JMP10雙分支2.雙分支程序 兩個分支都有語句體,如何選擇條件不重要。流程圖中分支體的位置就是程序的實際順序,故分支語句體最后一定要有一條指令,跳過語句體,轉(zhuǎn)移到“后續(xù)操作”。條件成立?分支語句體2YN分支語句體1 后 續(xù) 操 作 11雙分支雙分支舉例:顯示BX的最高位。shl bx,1jc one ;轉(zhuǎn)分支體 mov

6、dl,0 ;分支體1 jmp next;轉(zhuǎn)后續(xù)操作One: mov dl,1 ;分支體2next: mov ah,2 ;后續(xù)操作 int 21h .分支程序的其他問題有些雙分支問題可以先假設(shè)一種情況,把雙分支改成單分支問題。如上例,先假設(shè)BX最高位為0,在分支外準(zhǔn)備顯示0;如最高位為0,即可直接跳到后續(xù)操作;如最高位為1才需要執(zhí)行分支體。 mov dl,0 shl bx,1 jnc next mov dl,1next:mov ah,2 int 21h12多分支分支的嵌套形成多分支,嵌套形式多種多樣。例1:求符號函數(shù) 1 當(dāng) X0Y= 0 當(dāng) X=0 -1 當(dāng) X0X0?YNX=0?YNY=-1

7、Y=1Y=0實際是雙分支的組合。13多分支例2:判斷AL各位的值,D0=1,轉(zhuǎn)移到L0;D1=1,轉(zhuǎn)移到L1;D2=1,轉(zhuǎn)移到L2D0=1分支L0D2=1D1=1分支L1分支L2yyyNNN 也可認為是雙分支的組合,但為簡化編程,實現(xiàn)左圖的分支結(jié)構(gòu)可以在數(shù)據(jù)段設(shè)置轉(zhuǎn)移地址表,如例題4.414多分支 例4.4 使用地址表實現(xiàn)多分支。8個分支的標(biāo)號分別為disp1,disp2在代碼段有:disp1:mov dx,disp2:mov 設(shè)disp1的偏移地址為2300h,disp2的偏移地址為2500h。在數(shù)據(jù)段有:tabel dw disp1,disp2,tabeldisp1disp4disp325

8、00H2300Hdisp5disp6disp7disp802468ACE相對tabel的偏移量15多分支(e)轉(zhuǎn)入分支:按輸入的數(shù)字轉(zhuǎn)入不同分支 按輸入的數(shù)字求出分支相對tabel的偏移量:disp1為0,disp2為2,disp3為4,如輸入數(shù)字2,則偏移量為(2-1)2=2,將求出的偏移量存入bx。 執(zhí)行指令jmp tabelbx,設(shè)bx=02 則IP tabel+bx 即IP 2500H CS:2500H為分支Disp2的入口,CPU即執(zhí)行分支DISP2返回第四章164.3 循環(huán)程序設(shè)計4.3 循環(huán)程序設(shè)計(重復(fù)執(zhí)行的程序段)1.循環(huán)程序的組成初始化部分:設(shè)置循環(huán)條件、次數(shù)、初值等。循環(huán)

9、體部分:重復(fù)執(zhí)行的代碼,含循環(huán)條件的修改等。循環(huán)控制部分:判斷循環(huán)條件,決定是否繼續(xù)。2.兩種循環(huán)結(jié)構(gòu)1) “先循環(huán)、后判斷”結(jié)構(gòu)相當(dāng)于高級語言的“直到型”循環(huán)2) “先判斷、后循環(huán)”結(jié)構(gòu)相當(dāng)于高級語言的“當(dāng)型循環(huán)”,可實現(xiàn)0次循環(huán)。17兩種循環(huán)結(jié)構(gòu)初 始 化 部 分循 環(huán)條件成立?循 環(huán) 體 部 分(修改循環(huán)條件) NY循 環(huán)條件成立?初 始 化 部 分循 環(huán) 體 部 分(修改循環(huán)條件) YN18循環(huán)程序設(shè)計3.循環(huán)程序設(shè)計編寫循環(huán)程序的關(guān)鍵在于循環(huán)的控制。循環(huán)次數(shù)已知:可用LOOP指令,CX計數(shù)。如教材例4.5。循環(huán)次數(shù)和ZF標(biāo)志:可用LOOPZ、LOOPNZ指令。如教材例4.6。循環(huán)次數(shù)

10、未知:通常要采用各類條件轉(zhuǎn)移指令實現(xiàn)循環(huán)控制。如教材例4.7,字符串以0結(jié)尾;例4.9,字符串以$結(jié)尾。19例題分析 循環(huán)程序例題分析: 例4.5:計算100個數(shù)字之和。 僅用循環(huán)次數(shù)控制,且循環(huán)次數(shù)已知,比較簡單。 例4.6:確定一個字變量中為1的最低位數(shù)。 從最低位向高位依次測試,最多測試16次;測試到某位為1,即可結(jié)束程序,測試結(jié)果用ZF標(biāo)志反映,因此可用LOOPE或LOOPZ控制循環(huán)(結(jié)果非0,退出)。 例4.7:將一個字符串中的所有大寫字母改為小寫字母,字符串以0結(jié)尾。 循環(huán)次數(shù)未知,應(yīng)使用條件判斷控制循環(huán);循環(huán)結(jié)構(gòu)應(yīng)使用“先判斷、后執(zhí)行”的結(jié)構(gòu);通常,采用條件判斷控制循環(huán)時,往往采

11、用“先判斷、后執(zhí)行”的循環(huán)結(jié)構(gòu)。 20例題4.6例4.6:確定一個字變量中為1的最低位數(shù)。 .startupmov ax,wordX;測試目標(biāo)送AXmov cx,16;循環(huán)計數(shù)器置初值mov dl,-1;計位器置初值again:inc dltest ax,1ror ax,1 ;循環(huán)指令不影響ZFloope again ;CX0且ZF=1(測試位為0),繼續(xù)循環(huán)je notfound ;退出循環(huán),但0標(biāo)志成立,沒有1mov byteY,dljmp donenotfound:mov byteY,-1;ZF=1,16個位均為0done:.exit 0 end21例題4.7/1例4.7:將一個字符串中

12、的所有大寫字母改為小寫字母,字符串以0結(jié)尾。.dataSteing db xxxxxxxxxxxxxxxxxx,0.code.startupmov bx,offset stringagain: mov al,bx ;取一個字符 or al,al ;是否為結(jié)尾符0 jz done ;是,退出循環(huán) 22 /2 cmp al,A ;是否為大寫AZ jb next cmp al,Z ja next or al,20h ;是,轉(zhuǎn)換為小寫字母(使 D5=1) mov bx,al;仍保存在原位置next: inc bx jmp again;繼續(xù)循環(huán)done: .exit 0 end23兩重循環(huán)結(jié)構(gòu) 4.多重

13、循環(huán):循環(huán)程序的嵌套構(gòu)成多重(多層)循環(huán)。最常見的多重循環(huán)為兩重循環(huán)。外循環(huán)初始化內(nèi)循環(huán)初始化內(nèi)層循環(huán)體外層循環(huán)體內(nèi)循環(huán)結(jié)束外循環(huán)結(jié)束NNYY一個簡單延時程序:(雙重循環(huán)) mov cx,100n_start: mov dx,0ffffhn_loop: dec dx jnz n_loop dec cx jnz n_start內(nèi)循環(huán)控制外循環(huán)控制24“冒泡法”排序 例4.8:采用“冒泡法”排序(升序)。 冒泡法從第一個元素開始,依次對相鄰的兩個元素進行比較,使前一個元素不大于后一個元素;將所有元素比較完之后,最大的元素排到了最后;第一輪比較結(jié)束。然后,開始第二輪,除掉最后一個元素,其他元素依上述

14、方法再進行比較,得到次大的元素排在后面;第二輪結(jié)束。如此重復(fù),直至完成,就實現(xiàn)了元素從小到大的排序 循環(huán)次數(shù)已知的雙重循環(huán)程序。外層循環(huán)(輪)的次數(shù)為數(shù)據(jù)個數(shù)減1,每一輪外循環(huán)的內(nèi)層循環(huán)次數(shù)等于剩下的外循環(huán)次數(shù)。如5個數(shù)據(jù),外循環(huán)次數(shù)=4,第一輪中內(nèi)循環(huán)次數(shù)也為4;第一輪作完,還剩下3輪,第二輪中內(nèi)循環(huán)次數(shù)等于3,以次類推。 25“冒泡法”排序小數(shù)冒泡815163285158163285161583285321615885 1 32 2 85 3 16 4 15 5 8(1輪)4(2輪)3(3輪)2(4輪)1外 循 環(huán) 次 數(shù)(輪次)序號 數(shù)每 輪 內(nèi) 循 環(huán) 次 數(shù)4321大數(shù)沉底排序示意圖

15、須作4輪第1輪26例4.8 排序/1例4.8 對無符號字節(jié)數(shù)組元素由小到大排序。.dataArray db xx,xx,xx,Count equ ($-array)/(type array).code mov cx,count;CX數(shù)組元素個數(shù) dec cx ;元素個數(shù)減1為外循環(huán)次數(shù)outlp:mov dx,cx ;DX內(nèi)循環(huán)次數(shù) mov bx,offset arrayinlp:mov al,bx ;取前一個元素cmp al,bx+1 ;與后一個元素比較jna next ;前一個不大于后一個元素,則不進行交換xchg al,bx+1;否則,進行交換mov bx,al27例4.8 排序/2ne

16、xt:inc bx;下一對元素 dec dx jnz inlp;內(nèi)循環(huán)尾 loop outlp;外循環(huán)尾28例4.9 剔除空格程序例4.9:剔除以結(jié)尾的字符串中的空格。 雙重循環(huán)程序:外層循環(huán)負責(zé)搜索字符串中的空格;內(nèi)層循環(huán)負責(zé)剔除搜索到的空格(由于空格后的字符要依次向前移動一個字節(jié),因而也是一個循環(huán)結(jié)構(gòu))。 無論是外層循環(huán),還是內(nèi)層循環(huán),循環(huán)次數(shù)都未知,只能用“條件判斷”控制循環(huán)。 外層循環(huán)采用“先判斷、后循環(huán)”結(jié)構(gòu);對內(nèi)層循環(huán)而言,由于搜索到空格才進入內(nèi)循環(huán),所以采用“先循環(huán)、后判斷”結(jié)構(gòu)。29例4.9/1例4.9:現(xiàn)有一個以$結(jié)尾的字符串,要求剔除其中的空格。.datastringdb

17、Let us have a try !,$.code.startupmov dx,offset stringmov ah,9int 21h ;顯示原字符串mov al, ;AL空格(ASCII碼為20H)mov di,offset string30例4.9/2outlp:cmp byte ptr di,$;外循環(huán),先判斷后循環(huán)jz done ;為$結(jié)束cmp al,di ;檢測是否是空格jnz next ;不是空格繼續(xù)外循環(huán)mov si,di ;是空格,進入剔除空格分支inlp:inc si ;該分支是循環(huán)程序段mov ah,si ;取空格后的一個字符mov si-1,ah ;向前移動一個字節(jié)

18、cmp byte ptr si,$;內(nèi)循環(huán),先循環(huán)后判斷jnz inlp31例4.9/3next:inc di ;繼續(xù)對后續(xù)字符進行處理 jmp outlpdone:mov dx,offset string mov ah,9 int 21h ;顯示處理后字符串 .exit 0 ;結(jié)束 end返回第四章324.4 (目錄)子程序設(shè)計 4.4 子程序設(shè)計 把功能相對獨立的程序段單獨編寫和調(diào)試,作為一個相對獨立的模塊供程序使用,就形成子程序。 使用子程序:簡化源程序結(jié)構(gòu);提高編程效率。 4.4.1 過程定義偽指令 4.4.2 子程序的參數(shù)傳遞 4.4.3 子程序的嵌套遞歸重入 4.4.4 子程序的應(yīng)

19、用返回第四章334.4.1 過程定義偽指令(1)4.4.1 過程定義偽指令過程名 PROC NEAR|FAR 過程體 RET(RET N) 過程名 ENDP過程名:符合語法的標(biāo)識符;同模塊唯一性。距離屬性:可省略,由匯編程序判斷。堆棧使用:平衡。才能保證RET指令彈出的是斷點地址。保護現(xiàn)場與恢復(fù)現(xiàn)場:子程序用到的寄存器或存儲單元,注意:后進先出。注意子程序的規(guī)范和格式PUSH AXPUSH BXPUSH CXPUSH DXPOP DXPOP CXPOP BXPOP AX34 關(guān)于“距離屬性” 關(guān)于“距離屬性”NEAR屬性(段內(nèi)近調(diào)用)的過程只能被相同代碼段的其他程序調(diào)用FAR屬性(段間遠調(diào)用)

20、的過程可以被相同或不同代碼段的程序調(diào)用 對簡化段定義格式,在微型、小型和緊湊存儲模式下,過程的缺省屬性為near;在中型、大型和巨型存儲模式下,過程的缺省屬性為far 對完整段定義格式,過程的缺省屬性為near用戶可以在過程定義時用near或far改變?nèi)笔傩?5 子程序規(guī)范子程序規(guī)范 一個完整的子程序,特別是供其他編程人員使用的子程序,必須附有一個詳細說明:子程序名(過程名)子程序功能介紹子程序的入口參數(shù)子程序的出口參數(shù)子程序內(nèi)使用的寄存器(存儲單元)使用該子程序的范例子程序名:DTOB功能:完成兩位十進制數(shù)轉(zhuǎn)換成二進制數(shù)入口參數(shù):AL存放待轉(zhuǎn)換的兩位BCD碼出口參數(shù):CL存放轉(zhuǎn)換后的二進制

21、數(shù)占用寄存器:BX示例:輸入AL=01010110B (56H) 輸出CL=00111000B (38H)某子程序的說明36 子程序的常見格式子程序的常見格式;子程序說明;子程序說明subnameproc;具有缺省屬性的subname過程push ax;保護寄存器:順序壓入堆棧push bx;ax/bx/cx僅是示例push cx;過程體pop cx;恢復(fù)寄存器:逆序彈出堆棧pop bxpop axret;過程返回subnameendp;過程結(jié)束37 簡單子程序 簡單子程序;子程序功能:實現(xiàn)光標(biāo)回車換行dpcrlfproc ;過程開始push ax ;保護寄存器AX和DXpush dxmov

22、dl,0dh ;顯示回車mov ah,2int 21hmov dl,0ah ;顯示換行mov ah,2int 21hpop dx ;恢復(fù)寄存器DX和AXpop axret ;子程序返回dpcrlfendp ;過程結(jié)束38 例4.10:編寫子程序(e)例4.10:編寫子程序,將AL寄存器內(nèi)的二進制數(shù)用十六進制數(shù)顯示。8位二進制數(shù),可轉(zhuǎn)換成兩位十六進制數(shù)。十六進制數(shù)ASCII碼2#功能調(diào)用顯示1001B9H1001+0011 000039H(9的ASCII)1010BAH1010+0011 011141H(A的ASCII)注意:對0-9加30H,對A-F加37H,即+30H+07H先轉(zhuǎn)換高4位二進

23、制數(shù),并顯示;然后轉(zhuǎn)換低4位并顯示。例題410回 4.4394.4.2 子程序的參數(shù)傳遞 4.4.2 子程序的參數(shù)傳遞 主程序和子程序之間通常需要傳遞參數(shù):入口參數(shù)(輸入?yún)?shù)):主程序提供給子程序出口參數(shù)(輸出參數(shù)):子程序返回給主程序參數(shù)的形式: 數(shù)據(jù)本身(傳值) 數(shù)據(jù)的地址(傳址)傳遞的方法: 寄存器 變量 堆棧40參數(shù)傳遞方法 1.用寄存器傳遞參數(shù)方便、簡單、易行。須要傳遞的參數(shù)較多時不適用。見例題411a。2.用變量傳遞參數(shù)就是用存儲器傳遞參數(shù),當(dāng)主程序與子程序在同一個模塊時,即為共享數(shù)據(jù)段的變量;不在同一模塊,需要用PUBLIC/EXTERN聲明。適用與參數(shù)較多情況。見例題411b。

24、3.用堆棧傳遞參數(shù)常用方法。用BP訪問堆棧段。須格外注意堆棧的平衡。(堆棧示意圖)41 堆棧示意圖使用堆棧傳遞參數(shù)時堆棧示意圖: PUSH 參數(shù)1PUSH 參數(shù)2PUSH 參數(shù)3CALL SUBPRO .EXIT 0SUBPRO PROC PUSH BP MOV BP,SP PUSH AX POP AX POP BP RET (RET 6)SUBPRO ENDPA XB PI P參數(shù)3參數(shù)2參數(shù)1BP=SPBP+2BP+4BP+6BP+8SP(原始)子程序取參數(shù):MOV AX,BP+4(6,8)子程序平衡堆棧:RET 6主程序平衡堆棧: ADD SP,6例題411cSP42例題4.11c/1例

25、題4.11c:計算累加和;用堆棧傳遞參數(shù);入口參數(shù):數(shù)組首地址、數(shù)組元素個數(shù);出口參數(shù):AL 累加和 .model small .stack .datacount equ 10array db 12h,25h,0f0h,0a3h,03,68h,71h,0cah,0ffh,90hresult db ?43例題4.11c/2 .code .startup mov ax,offset array push ax ;首地址入棧 mov ax,count push ax ;元素個數(shù)入棧 call checksuma add sp,4 ;平衡兩個參數(shù)占用的堆棧 mov result,al .exit 04

26、4例題4.11c/3checksuma proc push bp mov bp,sp;使BP指向剛進入子程序的堆棧頂, push bx push cx mov bx,bp+6 mov cx,bp+4 xor al,alsuma: add al,bx inc bx loop suma45例題4.11c/4 pop cx pop bx pop bp ret ;可以用RET 4checksuma endp end 46 編寫子程序時應(yīng)注意的問題 編寫子程序時應(yīng)注意的問題: 使用簡化的段定義格式時,過程定義在程序中的位置要注意,可以放在1)主程序的最后,即“.EXIT 0”之后,END語句之前;2)放

27、在主程序之前,即“.CODE”之后,“.STARTUP”之前。 使用寄存器傳遞參數(shù)時,帶有入口參數(shù)的寄存器可以保護,也可以不保護;帶有出口參數(shù)的寄存器則一定不可保護和恢復(fù);其他與出口參數(shù)無關(guān)、而子程序中使用的寄存器,子程序開始處應(yīng)該保護,子程序結(jié)束、返回主程序之前應(yīng)該恢復(fù)。回 4.4474.4.3 子程序的嵌套遞歸重入4.4.3 子程序的嵌套、遞歸與重入1.子程序的嵌套子程序又調(diào)子程序稱為子程序的嵌套,嵌套的層數(shù)取決于堆??臻g的大小。嵌套子程序的設(shè)計和一般子程序完全相同。2.子程序的遞歸子程序直接或間接地嵌套調(diào)用自己,稱為遞歸調(diào)用。含有遞歸調(diào)用的子程序稱為遞歸子程序。每次調(diào)用時不能破壞以前調(diào)用

28、所用的參數(shù)及中間結(jié)果,因此,調(diào)用參數(shù)及中間結(jié)果一般都放在堆棧中。不可放在固定的寄存器或存儲單元中。要控制遞歸的次數(shù),避免陷入死循環(huán)。遞歸深度受堆??臻g的限制。48 例題4.12例題4.12 用遞歸子程序求N的階乘,設(shè)N=3。遞歸次數(shù)用N控制,由N=3,子程序共運行4次(主程序調(diào)用1次,遞歸調(diào)用3次);入口參數(shù)及中間結(jié)果都用堆棧保存。注釋:1)在進入子程序過程中,不計算階乘值,只求中間參數(shù)。第一次進入,求出中間參數(shù)2;第二次進入求出中間參數(shù)1;第三次進入求出中間參數(shù)0;第四次進入后,由于中間參數(shù)以為0,開始執(zhí)行返回處理。 2)在返回過程中計算階乘:在過程3中計算1*1=1,在過程2中計算1*2=

29、2,在過程1中計算2*3=6。 3)遞歸子程序可設(shè)計出效率較高的程序,但是編程較難,編出的程序易讀性差,使用不多。49 子程序的重入(e)3.子程序的重入子程序被中斷后,又被中斷服務(wù)程序所調(diào)用,稱為子程序的重入。能夠重入的子程序稱為可重入子程序。當(dāng)主機與外設(shè)采用中斷方式交換信息時,外設(shè)的驅(qū)動程序應(yīng)按“可重入原則”設(shè)計。雖然重入與遞歸的概念不同,但遞歸子程序就是可重入子程序。設(shè)計可重入子程序與設(shè)計遞歸子程序的原則是相同的,即參數(shù)、中間結(jié)果等都用堆棧保存,不能用固定的存儲單元或寄存器保存?;?4.4504.4.4 子程序的應(yīng)用 4.4.4 子程序的應(yīng)用1)例題4.15 計算有符號數(shù)的平均值。 有時

30、進行運算之前,需要符號擴展;對無符號數(shù)應(yīng)進行0擴展。 2)具有局部變量的子程序(截取教材P123部分程序):當(dāng)某些數(shù)據(jù)只有子程序自己使用時,可在代碼段子程序后面定義數(shù)據(jù)區(qū)。 3)具有多個出口的子程序:有的子程序具有多個出口,根據(jù)條件的不同,從不同的出口返回主程序。51例4.15 計算平均值/1例4.15 計算有符號數(shù)的平均值。;入口參數(shù)用堆棧傳遞,出口參數(shù)用寄存器AX傳遞。;要計算16位有符號數(shù)的和,被加數(shù)一定要進行符號擴展。 .model small .stack .dataarray dw 1234,-1234,1,1,-1,32767,-32768,5678,-5678,9000 cou

31、nt equ ($-array)/2 ;數(shù)據(jù)個數(shù)wmed dw ?52 /2 .code .startup mov ax,count push ax ;參數(shù)1 mov ax,offset array push ax ;參數(shù)2 call mean add sp,4 ;平衡堆棧 mov wmed,ax .exit 053 /3mean proc push bp mov bp,sp push bx push cx push dx push si push di mov bx,bp+4;取參數(shù)2:偏移地址 mov cx,bp+6;取參數(shù)1:數(shù)據(jù)個數(shù) xor si,si mov di,si54 /4me

32、an1: mov ax,bx cwd add si,ax adc di,dx inc bx inc bx loop mean1 mov ax,si mov dx,di mov cx,bp+6 dx.ax + di.si di.si55 /5 idiv cx ;求平均值,商在AX,余數(shù)在DX pop di pop si pop dx pop cx pop bx pop bp retmean endp end 56避免溢出的方法為了避免有符號二進制數(shù)求和過程中溢出,被加數(shù)要進行符號擴展,得到倍長數(shù)據(jù)(大小沒有變化),然后求和如數(shù)據(jù)采用16位二進制數(shù)表示,數(shù)據(jù)個數(shù)也采用16位二進制數(shù)表示,則最多為2

33、16個數(shù)據(jù)。如將數(shù)據(jù)擴展到32位二進制數(shù)表示,求和時,就不會出現(xiàn)溢出??紤]極端情況:數(shù)據(jù)全是215(-32768),共有216個,求和結(jié)果是231,32位數(shù)據(jù)仍然可以表達。對于無符號數(shù),有時也需要得到倍長數(shù)據(jù),應(yīng)采用“0擴展”,即將高位置0,如“MOV DX,0”。57;將AL低4位表達的一位16進制數(shù)轉(zhuǎn)換為ASCII碼H2ASCprocpush bxmov bx,offset ASCII;BX指向ASCII碼表and al,0fh;取得一位16進制數(shù)xlat CS:ASCII;換碼:ALCS:BXAL,注意數(shù)據(jù)在代碼段CSpop bxret;子程序返回ASCIIdb 30h,31h,32h,

34、33h,34h,35h,36h,37hdb 38h,39h,41h,42h,43h,44h,45h,46hH2ASCendp例題 具有局部變量的子程序 因為數(shù)據(jù)區(qū)與子程序都在代碼段,所以利用了換碼指令XLAT的另一種助記格式(寫出指向緩沖區(qū)的變量名,目的是便于指明段超越前綴)。串操作MOVS、LODS和CMPS指令也可以這樣使用,以便使用段超越前綴 除采用段超越方法外,子程序與主程序的數(shù)據(jù)段不同時,我們還可以通過修改DS值實現(xiàn)數(shù)據(jù)存取;但需要保護和恢復(fù)DS寄存器58HTOASCproc;將AL低4位表達的一位16進制數(shù)轉(zhuǎn)換為ASCII碼and al,0fhcmp al,9jbe htoasc1

35、add al,37h;是0AH0FH,加37Hret;子程序返回htoasc1:add al,30h;是09,加30Hret;子程序返回HTOASCendp例題 具有多個出口的子程序回 4.459例4.13例4.13 編寫子程序從鍵盤輸入一個有符號十進制數(shù);并將輸入的ASCII碼轉(zhuǎn)換為二進制數(shù)。輸入時,負數(shù)用“”引導(dǎo),正數(shù)直接輸入或用“”引導(dǎo)子程序用寄存器傳遞出口參數(shù),主程序調(diào)用該子程序輸入10個數(shù)據(jù)將ASCII碼轉(zhuǎn)換為二進制數(shù)的過程 首先判斷輸入為正或負數(shù),并用一個寄存器記錄 接著輸入09數(shù)字(ASCII碼),并減30H轉(zhuǎn)換為二進制數(shù) 然后將前面輸入的數(shù)值乘10,并與剛輸入的數(shù)字相加得到新的

36、數(shù)值 重復(fù)、步,直到輸入一個非數(shù)字字符結(jié)束 負數(shù)進行求補,轉(zhuǎn)換成補碼;否則直接保存數(shù)值60輸入和轉(zhuǎn)換流程圖輸入和轉(zhuǎn)換流程圖:A負數(shù)求補,正數(shù)不變出口參數(shù)AX返回1號調(diào)用輸入字符是+?是-?置負數(shù)標(biāo)志輸入下一個0-9之間變成二進制數(shù)BX*10+ALBXYNNA輸入非數(shù)字字符,結(jié)束輸入61輸入數(shù)字舉例設(shè)從鍵盤輸入數(shù)字 258:輸入順序:- 2 5 8 CX -1 -1 -1 -1 BX 0 0002 0019H=25 0102H=258數(shù)字輸入結(jié)束后,由于CX為負數(shù)標(biāo)志,再對BX求補。 62程序/1.datacount= 10arraydw count dup(0);預(yù)留數(shù)據(jù)存儲空間.code.s

37、tartupmov cx,countmov bx,offset arrayagain:call read;調(diào)用子程序輸入一個數(shù)據(jù)mov bx,ax;將出口參數(shù)存放緩沖區(qū)inc bxinc bxcall dpcrlf ;調(diào)用子程序,光標(biāo)回車換行以便輸入下一個數(shù)據(jù)loop again.exit 0這是主程序63程序/2;輸入有符號10進制數(shù)的通用子程序;出口參數(shù):AX補碼表示的二進制數(shù)值read procpush bxpush cxpush dxxor bx,bx;BX保存結(jié)果xor cx,cx;CX為正負標(biāo)志,0為正,1為負mov ah,1;輸入一個字符int 21h64程序/3 cmp al,

38、+;是“”,繼續(xù)輸入字符jz read1cmp al,-;是“”,設(shè)置1標(biāo)志jnz read2;非“”和“”,轉(zhuǎn)read2mov cx,-1read1:mov ah,1;繼續(xù)輸入字符int 21hread2:cmp al,0;不是09之間的字符,則輸入數(shù)據(jù)結(jié)束jb read3cmp al,9ja read365程序/4 sub al,30h;是09之間的字符,則轉(zhuǎn)換為二進制數(shù);利用移位指令,實現(xiàn)數(shù)值乘10:BXBX10shl bx,1mov dx,bxshl bx,1shl bx,1add bx,dxmov ah,0add bx,ax ;已輸入數(shù)值乘10后,與新輸入數(shù)值相加jmp read1;

39、繼續(xù)輸入字符66程序/5read3:cmp cx,0jz read4neg bx ;是負數(shù),進行求補read4:mov ax,bx;設(shè)置出口參數(shù)pop dxpop cxpop bxret ;子程序返回readendpdpcrlfproc ;使光標(biāo)回車換行的子程序. ;省略dpcrlfendpend67例 4.14例4.14 編寫子程序,將二進制數(shù)轉(zhuǎn)換為10進制數(shù)的ASCII碼,并在屏幕上顯示一個有符號10進制數(shù)。顯示時,負數(shù)用“”引導(dǎo),正數(shù)直接輸出、沒有前導(dǎo)字符。子程序的入口參數(shù)用共享變量傳遞,主程序調(diào)用該子程序顯示10個數(shù)據(jù)。將二進制數(shù)轉(zhuǎn)換為10進制數(shù)的ASCII碼 首先判斷數(shù)據(jù)是零、正數(shù)或

40、負數(shù),是零顯示“0”退出 是負數(shù),顯示“”,求數(shù)據(jù)的絕對值; 接著數(shù)據(jù)除以10,余數(shù)加30H轉(zhuǎn)換為ASCII碼壓入堆棧 重復(fù)步,直到余數(shù)為0結(jié)束 依次從堆棧彈出各位數(shù)字,進行顯示68顯示數(shù)字舉例 顯示數(shù)字舉例:設(shè)AX中數(shù)據(jù)為-258的補碼1.顯示負號-。2.求補,AX中得到-258的絕對值。3.258/10,商為25,余數(shù)為8,此為個位。 8+30H,入棧。4.25/10,商為2,余數(shù)為5,此為十位。 5變ASCII碼入棧。5.2/10,商為0,余數(shù)為2,此為百位。 2變ASCII碼入棧。6.由于商為0,變換結(jié)束。7.順序出棧顯示。69程序/1.dataCount = 10Array dw 1

41、234,-1234,0,1,-1,32767,-32768, dw 5678,-78,9000Wtemp dw ? ;共享變量.code.startupmov cx,countmov bx,offset arrayagain:mov ax,bxmov wtemp,ax;將入口參數(shù)存入共享變量call write;調(diào)用子程序顯示一個數(shù)據(jù)inc bxinc bxcall dpcrlf;便于顯示下一個數(shù)據(jù)loop again.exit 070程序/2 ;顯示有符號10進制數(shù)的通用子程序 ;入口參數(shù):共享變量wtempwriteprocpush axpush bxpush dxmov ax,wtemp

42、;取出顯示數(shù)據(jù)test ax,ax;判斷零、正數(shù)或負數(shù)jnz write1mov dl,0;是零,顯示“0”后退出mov ah,2int 21hjmp write5 ;恢復(fù)現(xiàn)場后返回71程序/3write1:jns write2;不是負數(shù),轉(zhuǎn)向數(shù)據(jù)轉(zhuǎn)換。mov bx,ax ;是負數(shù),顯示“”mov dl,-mov ah,2int 21hmov ax,bxneg ax ;求絕對值write2:mov bx,10 ;準(zhǔn)備除數(shù)push bx ;10壓入堆棧,作為退出標(biāo)志72程序/4write3:cmp ax,0;數(shù)據(jù)(商)為零jz write4;轉(zhuǎn)向顯示sub dx,dx;擴展被除數(shù)DX.AXdiv

43、 bx ;數(shù)據(jù)除以10:DX.AX10add dl,30h ;余數(shù)(09)轉(zhuǎn)換為ASCII碼push dx ;數(shù)據(jù)各位先低位后高位壓入堆棧jmp write30032h0035h0038h10仍以 258為例25873程序/5write4:pop dx ;數(shù)據(jù)各位先高位后低位彈出堆棧 cmp dl,10 ;是結(jié)束標(biāo)志10,則退出 je write5 mov ah,2 ;進行顯示 int 21h jmp write4write5:pop dx pop bx pop ax ret ;子程序返回writeendp dpcrlfproc ;使光標(biāo)回車換行的子程序. ;省略dpcrlfendpend74

44、本章要點 本章要點:分支程序設(shè)計: 單分支、雙分支、多分支 單分支流程圖的畫法 用轉(zhuǎn)移地址表法實現(xiàn)多分支循環(huán)程序設(shè)計: 兩種循環(huán)結(jié)構(gòu) 循環(huán)程序的控制方法:計數(shù)法、條件判斷法 單層循環(huán)和雙層循環(huán)子程序設(shè)計: 過程定義偽指令 子程序的參數(shù)傳遞:寄存器、變量、堆棧75習(xí)題分析:補充11.將AX中存放的無符號數(shù)除以2,如果是奇數(shù),則加1后除以2(單分支)test ax,01h;測試AX最低位jz even ;最低位為0:AX為偶數(shù)add ax,1 ;最低位為1:AX為奇數(shù),需要加1even:rcr ax,1;AXAX2;如果采用SHR指令,則不能處理AXFFFFH的特殊情況76補充2/12.判斷一元二

45、次方程是否有實根。有,TAG置1; 無,TAG置0。(教材例題4.3:雙分支).dataa db ?b db ?c db ?tag db ?.code.startupmov al,bimul almov bx,ax;BX中為b277補充2/2 mov al,aimul cmov cx,4imul cx ;AX中為4ac(DX無有效數(shù)據(jù)) cmp bx,ax;比較二者大小jge yes ;條件滿足?mov tag,0 ;第一分支體:條件不滿足,tag0jmp done ;跳過第二個分支體yes:mov tag,1 ;第二分支體:條件滿足,tag1done:.exit 0 end78補充3/13.

46、按鍵盤輸入的數(shù)字1-8,轉(zhuǎn)8個分支(顯示不同的信息)。(同教材例題4.4,但顯示的信息不同)分析過程見課件4.2節(jié)的“多分支部分” .datamsg db Input number(18):,0dh,0ah,$Msg1 db Chapter 1 : .,0dh,0ah,$msg2 db Chapter 2 : .,0dh,0ah,$.msg8 db Chapter 8 : . ,0dh,0ah,$table dw disp1,disp2,disp3,disp4 dw disp5,disp6,disp7,disp8;取得各個標(biāo)號的偏移地址79補充3/2 start1:mov dx,offset

47、msg;提示輸入數(shù)字 mov ah,9 int 21h mov ah,1;等待按鍵 int 21h cmp al,1;數(shù)字 8? ja start1 and ax,000fh;將ASCII碼轉(zhuǎn)換成數(shù)字80補充3/3 dec ax shl ax,1;等效于add ax,ax mov bx,ax jmp tablebx ;(段內(nèi))間接轉(zhuǎn)移:IPtable+bxstart2:mov ah,9 int 21h .exit 0disp1: mov dx,offset msg1;處理程序1 jmp start2Disp2:. end81習(xí)題4.4 習(xí)題分析4.4 編寫一個程序,把從鍵盤輸入的一個小寫字母用

48、大寫字母顯示出來。 框圖:(省略輸入字符的判斷:簡單的順序程序)1號調(diào)用:輸入字符ALAL-20H2號調(diào)用:顯示字符結(jié) 束824.54.5 已知用于LED數(shù)碼管顯示的代碼表為: LEDTABEL DB 0C0H,0F9H(共16項數(shù)據(jù))依次表示09,AF這16個數(shù)碼的顯示代碼,編寫一個程序?qū)崿F(xiàn)將lednum中的一個數(shù)字轉(zhuǎn)換成對應(yīng)的LED顯示代碼。(查表程序)BX代碼表首地址ALlednum執(zhí)行指令XLATAL中即為所求的顯示代碼834.84.8 如果在例題4.4的tabel中依次添入msg1msg8,程序應(yīng)該如何修改?(Tabel dw msg1,.) mov bx,ax mov bx,ax

49、jmp tabelbx mov dx,tabelbxStart2: mov ah,9 mov ah,9 int 21h int 21h .exit 0 .exit 0 end 程序變得更加簡單。取顯示信息 偏移地址取轉(zhuǎn)移地 址送IP844.94.9 編制一個程序,將變量BUFX、BUFY中較大者送入BUFZ;若兩者相等,則把其中之一送入BUFZ中。設(shè)變量為無符號8位數(shù)。ALBUFXCMP AL,BUFYAL小于BUFY?ALBUFYBUFZALYNDONE:JAE DONE854.104.10 設(shè)變量bufX為有符號數(shù),編程將其符號狀態(tài)保存在singX,如X大于等于0,保存0;如X小于0,保存

50、-1。 該題為一個可以演變成單分支的雙分支結(jié)構(gòu):測試bufX符號0-1singX0singXnextY0singX測試bufX符號0-1singXnextY864.114.11 X、Y、Z是三個有符號16位數(shù)(教材誤印為16進制數(shù)),編寫程序: 1)三個數(shù)都不相等,顯示0; 2)有兩個數(shù)相等,顯示1; 3)三個數(shù)都相等,顯示2。 三個數(shù)比較,應(yīng)有5種情況: X=Y=Z 顯示2 X=YZ 顯示1 X=ZY 顯示1 XY=Z 顯示1 XYZ 顯示0 編程時必須要考慮到所有5種情況。874.11框圖X-ZX=Y=ZX=YZXY=ZX=ZYZF=1X-YX-ZY-ZXYZZF=1ZF=1ZF=0ZF=0ZF=1ZF=0884.134.13

溫馨提示

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

評論

0/150

提交評論