ch03 匯編程序設計_第1頁
ch03 匯編程序設計_第2頁
ch03 匯編程序設計_第3頁
ch03 匯編程序設計_第4頁
ch03 匯編程序設計_第5頁
已閱讀5頁,還剩71頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第三章匯編程序設計

編制匯編語言程序的步驟:(1)分析題意,確定算法(2)根據算法畫出程序框圖(3)根據框圖編寫程序(4)上機調試程序分支結構子程序結構程序結構:

復合結構:多種程序結構的組合…

順序結構循環結構按照指令執行的順序,程序的結構可以劃分成以下三種。

順序結構:程序按照它編寫的順序執行,每條指令只執行一

次,這樣的程序稱為“順序結構”的程序。

循環結構:一組指令被反復地執行,這樣的程序稱為“循環結

構”或者“重復結構”的程序。

選擇結構:根據某個條件,一部分指令被執行,另一部分指

令沒有被執行,這樣的程序稱為“選擇結構”或者

“分支結構”的程序。

程序基本結構3.1順序程序設計順序程序:沒有分支、循環等轉移指令,按指令書寫的前后順利依次執行最基本的程序結構完全采用順序結構編寫的程序并不多見例題順序程序設計實例采用查表法,實現一位16進制數轉換為ASCII碼顯示例數據段;數據段ASCII db30h,31h,32h,33h,34h,35h,36h,37h,38h,39h

;對應0~9的ASCII碼

db41h,42h,43h,44h,45h,46h

;對應A~F的ASCII碼hex db04h,0bh ;假設兩個要顯示的數據例代碼段

;代碼段movbx,offsetASCII ;BX指向ASCII碼表moval,hex ;AL取得一位16進制數 ;恰好就是ASCII碼表中的位移andal,0fh ;只有低4位是有效的,高4位清0Xlat

;換碼:AL←DS:[BX+AL]movdl,al ;入口參數:DL←ALmovah,2 ;02號DOS功能調用int21h ;顯示一個ASCII碼字符例代碼段(續)moval,hex+1 ;轉換并顯示下一個數據andal,0fhxlatmovdl,almovah,2int21h【例3?1】將16進制數字轉換為對應七段碼七段數碼管:7段LED發光管通過7個發光段的不同組合,能較好地顯示16進制數字(0,…,9,A,b,C,d,E,F)。每一段由一個二進制位控制它的亮或暗。可用一個字節來控制七段數碼管的顯示。各段順時針分別稱為a、b、c、d、e、f、g,有的產品還附帶有一個小數點h,依次對應D0~D7位。假定0表示對應段亮,1表示對應段暗,那么顯示數字0對應的控制碼應為11000000B,顯示數字1對應的控制代碼為11111001B,依此類推,顯示數字F對應的控制代碼為10001110B。這種用于控制七段數碼管亮暗的代碼就稱為七段碼。hgfedcbaDSEGSEGMENT

LEDTB DB0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H DB80H,90H,88H,83H,0C6H,0C1H,86H,8EH XDATA DB9 ;要顯示的16進制數字

XCODE DB? ;存放要顯示數字對應的七段碼DSEG ENDSCSEG SEGMENT ASSUMECS:CSEG,DS:DSEGSTART:MOVAX,DSEG MOVDS,AX

MOVBX,OFFSETLEDtb MOVAL,XDATA ;取16進制數字

ANDAL,0FH XLAT ;查表取得對應的七段碼

MOVXCODE,AL ;保存

MOVAX,4C00H INT21HCSEG ENDS ENDSTART3.2分支程序設計根據條件是真或假決定執行與否判斷的條件:各種指令(如CMP、TEST等)執行后形成的狀態標志分支控制:轉移指令Jcc和JMP可以實現分支結構有單分支結構雙分支結構多分支結構3.2.1單分支結構條件成立跳轉,否則順序執行分支語句體注意選擇正確的條件轉移指令和轉移目標地址【例3-2】求絕對值計算AL中有符號數的絕對值

cmpal,0

jgenonneg

;條件滿足(AL≥0),轉移

negal

;條件不滿足,求補nonneg:

movresult,al

;條件滿足

;不恰當的分支

cmpal,0

jlyesneg

;條件滿足(AL<0),轉移

jmpnonnegyesneg:

negal

;條件滿足,求補nonneg:

movresult,al

;條件不滿足3.2.2雙分支結構條件成立跳轉執行第2個分支語句體,否則順序執行第1個分支語句體注意第1個分支體后一定要有一個JMP指令跳到第2個分支體后【例3-3】顯示BX的最高位顯示BX的最高位

shlbx,1 ;BX最高位移入CF標志

jcone

;CF=1,即最高位為1,轉移

movdl,30h ;CF=0,即最高位為0:DL←30H=‘0’

jmptwo

;一定要跳過另一個分支體one: movdl,31h ;DL←31H=‘1’two: movah,2 int21h ;顯示可以用JNC替換JC顯示BX的最高位(另解1)

shlbx,1 ;BX最高位移入CF標志

jncone

;CF=0,即最高位為0,轉移

movdl,31h ;CF=1,即最高位為1:DL←31H=‘1’

jmptwo

;一定要跳過另一個分支體one: movdl,30h ;DL←30H=‘0’two: movah,2 int21h ;顯示轉換為單分支結構顯示BX的最高位(另解2)

movdl,’0’ ;DL←30H=‘0’ shlbx,1 ;BX最高位移入CF標志

jnctwo

;CF=0,即最高位為0,轉移

movdl,’1’

;CF=1,即最高位為1:DL←31H=‘1’two: movah,2 int21h ;顯示編寫分支程序,需留心分支的開始和結束顯示BX的最高位(無分支)

movdl,0 shlbx,1 ;BX最高位移入CF標志

adcdl,30h ;CF=0,DL←0+30h+0=30H=‘0’

;CF=1,DL←0+30h+1=31H=‘1’two: movah,2 int21h ;顯示大小寫字母轉換

;如果DL是一個小寫字母,則轉換為大寫

cmpdl,‘a’ ;小于小寫字母a,不需要處理

jbdisp cmpdl,‘z’ ;大于小寫字母z,也不需要處理

jadisp

subdl,20h

;是小寫字母,則轉換為大寫disp: ……轉換原理大小寫字母的比較和轉換‘A’=41H=01000001B‘B’=42H…‘Z’=5AH=01011001B‘a’=61H=01100001B‘b’=62H…‘z’=7AH=01111001B結論1:大小寫字母的ASCII碼值相差20H結論2:大小寫字母的ASCII碼值僅D5位不同方法1(加減指令):“ADDDL,20H”“SUBDL,20H”方法2(邏輯指令):“ORDL,20H”“ANDDL,0DFH”大小寫互換(異或指令):“XORDL,20H”[例3-4]將4位二進制轉換成對應的十六進制字符

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,AL3.2.3多分支結構如果可供選擇的程序塊多于兩個,這樣的結構稱為多分支選擇結構,如下圖(a)所示,下圖(b)是匯編語言程序的實現方法。【例3?5】編程實現符號函數:變量X和Y均為數據段中字節變量。

1(X>0)Y=0(X=0)X范圍:(-128~+127)-1(X<0)

MOVAL,X CMPAL,0 JGEBIGER

MOVAL,0FFH;X<0,-1送Y單元

JMPOKBIGER:JEOK;X=0,0送Y單元

MOVAL,1;X>0,1送Y單元

OK: MOVY,AL

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[例3-6]從鍵盤上輸入數字“1”到“3”,根據輸入選擇對應程序塊執行。INPUT: LEA DX,PROMPT MOV AH,9 INT 21H ;輸出提示信息

MOV AH,1 INT 21H ;輸入一個數字

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

JE F1 ;數字“1”,轉F1 CMP AL,‘2’ JE F2 ;數字“2”,轉F2 CMP AL,‘3’ JE F3 ;數字“3”,轉F3 JMP INPUT ;大于“3”,重新輸入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

DATA SEGMENT

PROMPT 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用地址表實現多分支START:MOVAX,DATA MOV DS,AXINPUT:LEA DX,PROMPT MOV AH,9 INT 21H ;顯示提示信息

MOV AH,1 INT 21H ;輸入一個數字

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

CMP AL,‘3’ JA INPUT ;不正確輸入,重新輸入

SUB AL,‘1’ ;將數字字符“1”到“3”轉換為0,1,2 SHL AL,1 ;轉換為0,2,4 MOV BL,AL MOV BH,0 ;轉入BX

JMP ADDTBL[BX] ;相對尋址,轉移到對應程序塊F1: LEA DX,MSG1 ;F1程序塊

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

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

JMP OUTPUT ;這條指令可以省略OUTPUT: MOV AH,9 INT 21H

MOV AX,4C00H INT 21HCODE ENDS END START3.3循環程序設計

循環結構也稱“重復結構”,一般由以下3個部分組成:(1)初始化部分:為循環做準備。 如:累加器清零,設置地址指針和計數器的初始值等。

工作部分:實現循環的基本操作。

修改部分:修改指針、計數器的值,為下一次循環做準備。

控制部分:判斷循環條件,確定結束或繼續循環。(3)結束部分:用來分析和存放程序的結果。(2)循環體部分兩種結構的循環:WHILE循環:先判斷循環條件,條件滿足則進入循環,循環次數最少為0次。DO-WHILE循環:先執行工作部分,然后判斷循環條件,條件滿足則轉向工作部分繼續循環,循環次數最少1次。計數循環:循環的次數事先已知,用一個變量(寄存器或存儲 器單元)記錄循環的次數(稱為“循環計數器”)。條件循環:循環的次數事先并不確定,根據某個條件是否滿足 來決定是否繼續循環。按照循環結束的條件,有以下兩類循環:用循環計數器的值來控制循環,也可以結合其它條件共同控制。[例]從鍵盤上輸入一個字符串(不超過80個字符),將它逆序后輸出。DATA SEGMENT BUFFERDB 81,?,81DUP(?) MESS DB 0AH,0DH,“Inputastringplease:”0AH,0DH,“$”DATA ENDSCODE 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 ;輸入字符串

LEA BX,BUFFER ;緩沖區首地址送BX MOV CL,BUFFER+1 MOV CH,0 ;輸入字符個數送CX(循環次數) ADD BX,CX

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

DEC BX ;修改指針

LOOP DISP ;計數循環

MOV AX,4C00H INT 21HCODE ENDS END START【例3-7】字節數組ARRAY存放有10個有符號數,找出最大數送字節變量MAX。DATASEGMENT

ARRAYDB-1,59,23,-45,116,107,159,25,218,-14 MAXDB?

DATAENDS

CODESEGMENT ASSUMECS:CODE,DS:DATASTART:MOVAX,DATA MOVDS,AX

MOVAL,ARRAY ;取數組第一個元素預設為最大數初值

MOVBX,OFFSETARRAY ;設置地址指針初值

MOVCX,9 ;設置比較次數3.3.1計數循環LOOPl:INC

BX

;修改地址指針,指向下一個要比較的數

CMPAL,[BX];比較

JGENEXT

;AL的數較大,直接結束本次比較,采用帶符號數轉移指令

MOVAL,[BX]

;AL的數較小,將該數置入AL,使AL始終是當前較大值NEXT: LOOPLOOPl

;計數循環控制,cx是否為0

MOVMAX,AL

;比較結束,保存最大值

MOVAX,4C00H INT 21HCODEENDS ENDSTART3.3.2條件循環DATA SEGMENT STRING DB “Astringfortesting.”,0

LENTH DW?DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATASTART:MOV AX,DATA MOV DS,AX[例]字符串STRING以代碼0結束,求這個字符串的長度(字符個數)

LEA SI,STRING ;設置地址指針初值

MOV CX,0 ;設置計數器初值TST: CMP BYTEPTR[SI],0;比較

JE DONE ;字符串結束,轉向DONE保存結果

INC SI ;修改指針

INC CX ;計數

JMP TST

;轉向TST,繼續循環DONE: MOV LENTH,CX ;保存結果

MOV AX,4C00H INT 21HCODE ENDS END START

……

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

MOV CX,-1

;裝載計數器初值TST: INC SI ;修改指針

INC CX ;計數

CMP BYTEPTR[SI],0

;比較

JNE TST ;未結束,轉TST繼續循環

MOV LENTH,CX ;字符串結束,保存結果

……比較一下,您喜歡這種風格嗎?【例3-8】編程完成求1+2+3+…N的累加和,直到累加和超過1000為止。統計被累加的自然數個數送N,累加和送SUM。假定N和SUM為已定義的字變量。DATASEGMENT

SUMDW?NDW?DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AX;設置DS

MOVAX,0;累加器AX清0

MOVBX,0;BX統計累加自然數個數,清0

LP:

INCBX;BX加1

ADDAX,BX;求累加和

CMPAX,1000;比較累加和是否大于1000

JBELP;≤1000轉,繼續累加

MOVSUM,AX;否則結束累加,保存累加和

MOVN,BX;保存累加的自然數個數

MOVAX,4C00HINT21H;返回DOSCODEENDSENDSTART;匯編結束【例3-9】統計BX寄存器中1的個數,并將結果存放在DL寄存器中。方法一:條件循環

MOVAX,BX XORDL,DL

L: ANDAX,AX

;測試AX中的數據是否為0,形成循環判斷條件

JZEXIT

;循環控制

SALAX,1

;循環體:實現一次統計。將AX中的最高位移入CF中

JNCL

;如果CF=0,轉L

INCDL

;如果CF=1,則(DL)+1→DL

JMPL

;轉L處繼續循環

EXIT: …方法二:計數循環

MOVAX,BX MOVCX,16 XORDL,DLNEXT:SALAX,1

;循環體:實現一次統計。

;將AX中的最高位移入CF中

JNCL

;如果CF=0,轉L處結束本次循環

INCDL;如果CF=1,則(DL)+1→DL

L:

LOOPNEXT

;循環控制:CX減1,判斷CX是否為0,不是0則循環EXIT: …DATA SEGMENT POSITION DW ? STRING DB “Thisisastringforexample.”,0DATA ENDSCODE SEGMENT ASSUME DS:DATA,CS:CODESTART:MOV AX,DATA MOV DS,AX

[例]查找字母’a’在字符串STRING中第一次出現的位置,如果未出現,置位置值為-1。 MOV SI,-1 ;SI用作字符串字符指針

MOV CX,30 ;字符串長度30L0: INC SI

;修改指針

CMP STRING[SI],‘a’ ;一個字符與’a’進行比較

LOOPNE L0 ;字符串未結束,未找到,繼續

JNE NOTFOUND ;未找到,轉“NOTFOUND”

MOV POSITION,SI ;保存位置值

JMP EXITNOTFOUND:MOV POSITION,-1 ;未找到,置位置值為-1EXIT: MOV AX,4C00H INT 21HCODE ENDS END START

字符串內找到字符’a’:循環結束時ZF=1,SI內是字符的出

現位置(從0開始);字符串內未找到字符’a’:循環結束時ZF=0,SI內是字符串

的長度-1(30-1=29)。程序使用LOOPNE指令來控制循環,既有計數控制,又有條件控制。循環結束有兩種可能性:3.3.3多重循環如果一個循環的循環體內包含了另一個循環,稱這個循環為“多重循環”,各層循環可以是計數循環或者條件循環。例:在多重循環的程序結構中,CX計數器的保存和恢復

MOVCX,MAGAIN:

……

PUSHCXMOVCX,NNEXT:……LOOPNEXT……

POPCX

LOOPAGAIN

MOVDI,MAGAIN:……MOVCX,NNEXT:……LOOPNEXT

……

DECDIJNZAGAIN【例3-10】有符號字節元素數組存有N個有符號數,要求將這N個數由小到大排列。DATA SEGMENT

ARRAY1DB 15H,0A7H,34H,55H,90H,7EH,3CH,25H,56H,0D6H N EQU$-ARRAY1DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATASTART: MOV AX,DATA MOV DS,AX ;***********開始排序***************

MOV CX,N-1

;設置外層循環計數器,CX中為排序的“遍數”(N-1);===================外層循環循環體開始=============LOOP1:PUSH CX ;保存外循環計數器

MOV BX,0

;BX=整序元素在數組內的位移,每一遍從第一個元素開始;-------內層循環循環體開始,CX的值是內層循環的次數------LOOP2:MOVAL,ARRAY1[BX] CMPAL,ARRAY1[BX+1] ;鄰元素比較

JLENEXT ;不需要整序,轉NEXT

XCHGAL,ARRAY1[BX+1] ;交換鄰元素位置

XCHGAL,ARRAY1[BX]NEXT:

INC BX ;修改指針

LOOP LOOP2 ;本遍未結束,轉LOOP2繼續;----------內層循環循環體結束---------------

POP CX ;恢復外層循環計數器

LOOP LOOP1 ;“遍數”未滿,轉LOOP1繼續;=============外層循環循環體結束================ MOV AX,4C00H INT 21HCODE ENDS END START【例3-11】有4名學生參加5門課程的考試,試計算每個學生的平均成績和每門課的平均成績。DATASEGMENT

GRADEDB80,95,76,83,92DB65,81,78,84,78DB90,86,96,100,83DB79,69,88,73,56 STUDB4DUP(?)

COURSEDB5DUP(?)DATAENDS

CODESEGMENT

ASSUMECS:CODE,DS:DATASTART:MOVAX,DATA MOVDS,AX

;*****************求每個學生的平均成績****************

MOVDI,4;設置外層循環計數器,DI中為學生人數

LEABX,GRADE;設置地址指針,BX指向成績表GRADELEASI,STU;設置地址指針,SI指向學生平均分表STU;===================外層循環循環體開始=============

L11:MOVAX,0;累加器清0

MOVCX,5;設置內層循環計數器,CX中為課程數;-----------------內層循環循環體開始----------------

L22:ADDAL,[BX]ADCAH,0;累加,考慮可能的進位

INCBX;修改地址指針

LOOPL22;內層循環控制;------內層循環循環體結束,AX中為某學生5門課總成績-----

MOVDL,5DIVDL;求平均值,保存在AL中

MOV[SI],AL;保存平均值

INCSI;修改地址指針

DECDI;修改外層循環計數值DIJNZL11;外層循環控制;===================外層循環循環體結束=============;**************以下為求每門課的平均成績**************

LEADI,GRADE;設置地址指針,DI指向成績表GRADELEASI,COURSE;設置地址指針,SI指向課程平均分表COURSE;MOVDI,BXMOVCX,5;設置外層循環計數器,CX中為課程數;===================外層循環循環體開始=============

L01:PUSHCX;外層循環計數值CX入棧保護

MOVBX,DI;設置內層循環地址指針

MOVAX,0;累計器清0MOVCX,4;設置內曾循環計數器,CX中為學生數;-----------------內層循環循環體開始----------------

L02:ADDAL,[BX]ADCAH,0;累加,考慮可能的進位

ADDBX,5;修改地址指針,指向下一個學生本課程地址

LOOPL02;內層循環控制;----內層循環循環體結束,AX中為某門課4名學生的總成績----MOVDL,4DIVDL;求課程平均成績,在AL中

MOV[SI],AL;保存課程平均成績

INCSI;修改外層循環COURSE表地址指針

INCDI;修改外層循環GRADE表地址指針

POPCX;恢復外層循環計數值

LOOPL01;外層循環控制;===================外層循環循環體結束=============

MOVAX,4C00HINT21HCODEENDSENDSTART3.4子程序設計

子程序名 PROC [NEAR/FAR]

PUSH …… ;保護現場(寄存器/存儲器)

PUSH …… ;個數根據具體情況決定

…… ;子程序主體

……

POP …… ;恢復現場,注意出棧次序

POP …… ;先進棧的寄存器后出棧

RET ;返回

子程序名

ENDP子程序的基本格式設計一個子程序之前,首先應該明確:子程序的名字;子程序的功能;入口參數:主程序調用子程序時,提供給子程序的參數出口參數:子程序執行結束返回給主程序的參數影響寄存器:執行這個子程序會改變哪幾個寄存器的值?其它需要說明的事項。上述內容連同子程序源代碼等合稱為“子程序文件”。常常把上述內容以“程序注釋”的方式書寫在一個子程序的首部。;名稱:Square;功能:求16Bit無符號數的平方根;入口參數:16Bit無符號數在AX中;出口參數:8Bit平方根數在AL中;影響寄存器:AX(AL)例3-12,一個名為“SQUARE”的子程序,用來求一個數的平方根,源程序如下:SQUARE PROC NEAR PUSH CX ;保護現場

PUSH BX

MOV BX,AX ;要求平方根的數送BX MOV AL,0 ;AL中存放平方根,初值0 MOV CX,1 ;CX置入第一個奇數1

;利用公式:N2=1+3+……+(2N-1)求平方根NEXT: SUB BX,CX JB DONE ADD CX,2 ;形成下一個奇數

INC AL ;AL存放已減去奇數的個數

JMP NEXTDONE: POP BX ;恢復現場

POP CX RET ;返回SQUARE ENDP子程序應用每調用一次子程序,主程序需要做三件事:(1)為子程序準備入口參數(2)調用子程序(3)處理子程序的返回參數DATA SEGMENTX DW 59,3500,139,199,77;欲求平方根的數組ROOT DB 5DUP(?)

;存放平方根內存區DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATASTART:MOV AX,DATA MOV DS,AX[例3-12]

求5個無符號數的平方根,主程序如下:

LEA BX,X ;初始化指針

LEA SI,ROOT MOV CX,5 ;設置計數器初值ONE: MOV AX,[BX] ;設置入口參數

CALL SQUARE ;調用子程序

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

ADD BX,2 ;修改指針

INC SI ;修改指針

LOOP ONE ;循環控制

MOV AX,4C00H ;返回DOS INT 21H

主程序部分;名稱:Square;功能:求16Bit無符號數的平方根;入口參數:16Bit無符號數在AX中;出口參數:8Bit平方根數在AL中;影響寄存器:AX(AL)SQUARE PROC NEAR PUSH CX ;保護現場

PUSH BX

MOV BX,AX ;要求平方根的數送BX MOV AL,0 ;AL中存放平方根,初值0 MOV CX,1 ;CX置入第一個奇數1

;利用公式:N2=1+3+……+(2N-1)求平方根NEXT:

SUB BX,CX JB DONE ADD CX,2 ;形成下一個奇數 INC AL ;AL存放已減去奇數的個數 JMP NEXTDONE: POP BX ;恢復現場 POP CX RET ;返回SQUARE

ENDPCODE ENDS

END

START子程序安排在主程序執行終止返回DOS后的位置子程序編寫注意事項⑴子程序要利用過程定義偽指令聲明⑵子程序最后利用RET指令返回主程序,主程序執行CALL指令調用子程序⑶子程序中對堆棧的壓入和彈出操作要成對使用,保持堆棧的平衡⑷子程序開始應該保護使用到的寄存器內容,子程序返回前相應進行恢復⑸子程序應安排在代碼段的主程序之外,最好放在主程序執行終止后的位置(返回DOS后、匯編結束END偽指令前),也可以放在主程序開始執行之前的位置子程序編寫注意事項⑹子程序可以與主程序共用一個數據段,也可以使用不同的數據段(注意修改DS),還可以在子程序最后設置數據區(利用CS尋址)⑺子程序允許嵌套和遞歸⑼處理好子程序與主程序間的參數傳遞問題⑽提供必要的子程序說明信息【例3-13】含數據區的子程序;子程序HTOASC:將AL低4位表示的十六進制數轉換為ASCII碼HTOASC proc pushbx movbx,offsetASCII andal,0fh xlatCS:ASCII

;換碼:AL←CS:[BX+AL] popbx

ret;數據區ASCII db30h,31h,32h,33h,34h,35h,36h,37h,38h,39h db41h,42h,43h,44h,45h,46hHTOASC endp【例3-14】

子程序嵌套示例,本例中子程序嵌套調用了例3-13子程序HTOASC。;入口參數:AL中為要顯示輸出的二進制數ALDISPPROC

PUSHAX;保護入口參數PUSHCX

PUSHAX;暫存數據

MOVCL,4SHRAL,CL;轉換AL的高4位

CALLHTOASC;子程序調用(嵌套)

POPAX;轉換AL的低4位

CALLHTOASC;子程序調用(嵌套)POPCXPOPAXRET;子程序返回ALDISPENDP【例3-15】子程序遞歸調用示例。編程計算N!,N!=N×(N-1)×(N-2)×…×2×1(N≥0)DATASEGMENT

NDW3 RESULTDW? ;保存結果DATAENDSCODESEGMENT ASSUMECS:CODE,DS:DATASTART:MOVAX,DATA MOVDS,AX

PUSHN ;入口參數N入棧

CALLFACT ;子程序FACT調用,求N!

POPRESULT ;出口參數彈出至RESULT MOVAX,4C00H ;返回DOS INT21H主程序部分;入口參數:N壓入堆棧(采用堆棧傳遞參數);出口參數:N!值在棧頂FACTPROC

PUSHAX PUSHBP PUSHDX

MOVBP,SP MOVAX,[BP+8] ;從堆棧中取入口參數

CMPAX,0 ;比較入口參數是否為0

JNEFACT1 ;不為0,則轉遞歸調用控制

INCAX ;如果為0,設置出口參數為0!=1

JMPFACT2子程序部分FACT1:DECAX ;設置求(N-1)!的入口參數值

PUSHAX ;入口參數入棧

CALLFACT ;遞歸調用,求(N-1)!

POPAX ;出口參數彈出至AX

MULWORDPTR[BP+8] ;求(N)!=N×(N-1)!FACT2:MOV[BP+8],AX

;設置出口參數,假定N!不會超出AX的表示范圍 POPDX POPBP POPAX

RETFACTENDPCODEENDS ENDSTART子程序部分多出口子程序;子程序HTOASC:將AL低4位表示的十六進制數轉換為ASCII碼HTOASC proc andal,0fh cmpal,9 jbehtoasc1 addal,37h ;是A~F,加37H ret ;子程序返回htoasc1: addal,30h ;是0~9,加30H

ret ;子程序返回HTOASC endp子程序的參數傳遞主程序與子程序間一個主要問題是參數傳遞入口參數(輸入參數):主程序調用子程序時,提供給子程序的參數出口參數(輸出參數):子程序執行結束返回給主程序的參數參數的具體內容傳數值:傳送數據本身傳地址:傳送數據的主存地址常用的參數傳遞方法寄存器共享變量堆棧1.用寄存器傳遞參數最簡單和常用的參數傳遞方法是通過寄存器,只要把參數存于約定的寄存器中就可以了由于通用寄存器個數有限,這種方法對少量數據可以直接傳遞數值,而對大量數據只能傳遞地址采用寄存器傳遞參數,注意帶有出口參數的寄存器不能保護和恢復,帶有入口參數的寄存器可以保護、也可以不保護,但最好能夠保持一致2.用共享變量傳遞參數子程序和主程序使用同一個變量名存取數據就是利用共享變量(全局變量)進行參數傳遞如果變量定義和使用不在同一個源程序中,需要利用PUBLIC、EXTRN聲明如果主程序還要利用原來的變量值,則需要保護和恢復利用共享變量傳遞參數,子程序的通用性較差,但特別適合在多個程序段間、尤其在不同的程序模塊間傳遞數據3.用堆棧傳遞參數參數傳遞還可以通過堆棧這個臨時存儲區。主程序將入口參數壓入堆棧,子程序從堆棧中取出參數;子程序將出口參數存入堆棧,主程序彈出堆棧取得它們采用堆棧傳遞參數是程式化的,它是編譯程序處理參數傳遞、以及匯編語言與高級語言混合編程時的常規方法【例3-16】編程采用子程序結構實現數組元素求和DATASEGMENT

ARY1DW1,2,3,4,5,6,7,8,9,10COUNT1DW($-ARY1)/2 ;ARY1元素個數

SUM1DW?DATAENDS入口參數: 數組的邏輯地址(傳址) 元素個數(傳值)出口參數: 求和結果(傳值)

;設置入口參數(含有DS←數組的段地址)

MOVBX,OFFSETARY1 ;BX←數組的偏移地址

MOVCX,COUNT1 ;CX←數組的元素個數

CALLPROADD1 ;調用求和子程序

MOVSUM1,AX ;處理出口參數

主程序1、通過寄存器傳遞參數;子程序名:PROADD1;功能:求字數組各元素之和;入口參數:

DS:BX=數組的段地址:偏移地址

CX=元素個數,

;出口參數:

AX=數組元素和;影響寄存器:AX子程序PROADD1PROC

PUSHCX

PUSHBX

XORAX,AX ;累加器清0

SUMA:

ADDAX,[BX] ;求和

INCBX;修改地址指針,指向下一個數據

INCBX

LOOPSUMA

POPBX POPCX

RETPROADD1ENDPdatasegmentary1dw1,2,3,4,5,6,7,8,9,10count1dw($-ARY1)/2sum1dw?ary2dw10,20,30,40,50,60,70,80,90,100count2dw($-ARY2)/2sum2dw?dataends2.通過共享變量傳遞參數datasegmentary1dw1,2,3,4,5,6,7,8,9,10count1dw($-ARY1)/2sum1dw?

ary2dw10,20,30,40,50,60,70,80,90,100count2dw($-ARY2)/2sum2dw?

tabledw3dup(?);地址表dataends累加數組中的元素(地址表)codesegmentassumecs:code,ds:datastart:pushdssubax,axpushaxmovax,datamovds,ax

movtable,offsetary1movtable+2,offsetcoun

溫馨提示

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

評論

0/150

提交評論