第6章子程序結(jié)構(gòu)_第1頁
第6章子程序結(jié)構(gòu)_第2頁
第6章子程序結(jié)構(gòu)_第3頁
第6章子程序結(jié)構(gòu)_第4頁
第6章子程序結(jié)構(gòu)_第5頁
已閱讀5頁,還剩53頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、第第6章子程序結(jié)構(gòu)章子程序結(jié)構(gòu)本章重點(diǎn)本章重點(diǎn) 1)子程序的概念、基本結(jié)構(gòu)形式、子程序)子程序的概念、基本結(jié)構(gòu)形式、子程序的現(xiàn)場保護(hù)和恢復(fù)及子程序的調(diào)用和返的現(xiàn)場保護(hù)和恢復(fù)及子程序的調(diào)用和返回回2)子程序設(shè)計(jì)的步驟和方法)子程序設(shè)計(jì)的步驟和方法3)主程序和子程序間傳遞參數(shù)的三種方法)主程序和子程序間傳遞參數(shù)的三種方法4)常用)常用DOS系統(tǒng)功能調(diào)用系統(tǒng)功能調(diào)用 61 子程序的設(shè)計(jì)方法子程序的設(shè)計(jì)方法 過程定義偽操作過程定義偽操作 子程序的調(diào)用和返回子程序的調(diào)用和返回 保存與恢復(fù)寄存器保存與恢復(fù)寄存器 子程序的變量傳送子程序的變量傳送 增強(qiáng)功能的過程定義偽操作增強(qiáng)功能的過程定義偽操作6.1.1

2、過程定義偽操作過程定義偽操作 主程序:主程序:為完成某一總體功能或任務(wù)而為完成某一總體功能或任務(wù)而編制的程序編制的程序 子程序:子程序:僅完成部分功能又可被多次調(diào)僅完成部分功能又可被多次調(diào)用的程序用的程序 過程定義偽操格式過程定義偽操格式 : procedure name PROC Attribute procedure name ENDP屬性屬性(Attribute) 調(diào)用程序和過程在同一個代碼段中,使調(diào)用程序和過程在同一個代碼段中,使用用NEAR屬性;屬性; 調(diào)用程序和過程不在同一個代碼段中,調(diào)用程序和過程不在同一個代碼段中,使用使用FAR屬性屬性 過程名:過程名:標(biāo)識符,它又是子程序入口

3、的標(biāo)識符,它又是子程序入口的符號地址符號地址 一般,主過程一般,主過程N(yùn)應(yīng)定義為應(yīng)定義為FAR屬性屬性例:調(diào)用程序和子程序在同一代碼段中例:調(diào)用程序和子程序在同一代碼段中 Code segmentMAIN PROC FARCALL SUBR1 RETMAIN ENDPSUBR1 PROC NEARRETSUBR1 ENDP Code ends過程定義嵌套過程定義嵌套 Code segmentMAIN PROC FAR CALL SUBR1 RET SUBR1 PROC NEAR RET SUBR1 ENDP MAIN ENDPCode ends調(diào)用程序和子程序不在同一個代碼段內(nèi)調(diào)用程序和子程序

4、不在同一個代碼段內(nèi) SEGX SEGMENT SUBT PROC FAR RETSUBT ENDP CALL SUBT SEGX ENDSSEGY SEGMENT CALL SUBT SEGY ENDS6.1.2 子程序的調(diào)用和返回子程序的調(diào)用和返回 CALL:指令完成調(diào)用功能指令完成調(diào)用功能 RET:指令完成返回功能指令完成返回功能 子程序中對堆棧的使用要特別小心,子程序中對堆棧的使用要特別小心,以以免返回錯誤免返回錯誤子程序的調(diào)用指令子程序的調(diào)用指令CALL使用使用 CALL調(diào)用指令:調(diào)用指令:CALL DST 段內(nèi)直接調(diào)用:如段內(nèi)直接調(diào)用:如CALL htod 段內(nèi)間接調(diào)用:如段內(nèi)間接調(diào)

5、用:如CALL NEAR PTR TABLESICALL BX 段間直接遠(yuǎn)調(diào)用:如段間直接遠(yuǎn)調(diào)用:如 CALL FAR PTR HtoD 段間間接遠(yuǎn)調(diào)用:如段間間接遠(yuǎn)調(diào)用:如CALL FAR PTR TABLESI子程序的返回指令子程序的返回指令RET使用使用 段內(nèi)近返回段內(nèi)近返回 段內(nèi)帶立即數(shù)近返回:格式段內(nèi)帶立即數(shù)近返回:格式RET EXP 如如 RET 6 段間遠(yuǎn)返回段間遠(yuǎn)返回 段間帶立即數(shù)遠(yuǎn)返回:格式段間帶立即數(shù)遠(yuǎn)返回:格式RET EXP注意返回時堆棧指針的變化注意返回時堆棧指針的變化6.1.3保存與恢復(fù)寄存器保存與恢復(fù)寄存器 情況:情況:如果主程序在調(diào)用子程序以前的某個寄如果主程序在

6、調(diào)用子程序以前的某個寄存器內(nèi)容在從子程序返回后還有用,而子程序存器內(nèi)容在從子程序返回后還有用,而子程序又恰好使用了同一個寄存器,可能使該寄存器又恰好使用了同一個寄存器,可能使該寄存器的原有內(nèi)容丟失,造成程序運(yùn)行錯誤的原有內(nèi)容丟失,造成程序運(yùn)行錯誤 解決辦法:解決辦法:在一進(jìn)入子程序后就應(yīng)把子程序所在一進(jìn)入子程序后就應(yīng)把子程序所需要使用的寄存器內(nèi)容保存在堆棧中,而在退需要使用的寄存器內(nèi)容保存在堆棧中,而在退出子程序前把寄存器內(nèi)容恢復(fù)原狀出子程序前把寄存器內(nèi)容恢復(fù)原狀 SUBT PROC NEAR PUSH AX PUSH BX PUSH CX PUSH DX 放子程序主要部分放子程序主要部分 P

7、OP DX POP CX POP BX POP AX RETSUBEND寄存器內(nèi)容保存寄存器內(nèi)容保存 寄存器內(nèi)容恢復(fù)寄存器內(nèi)容恢復(fù) 286保存所有寄存器內(nèi)容保存所有寄存器內(nèi)容 PUSHA恢復(fù)所有寄存器內(nèi)容恢復(fù)所有寄存器內(nèi)容 POPA 386-保存所有寄存器內(nèi)容保存所有寄存器內(nèi)容 PUSHAD恢復(fù)所有寄存器內(nèi)容恢復(fù)所有寄存器內(nèi)容 POPAD所有寄存器所有寄存器6.1.4 子程序的變量傳送子程序的變量傳送 一、通過寄存器傳送變量一、通過寄存器傳送變量二、過程和調(diào)用程序在同一源文件二、過程和調(diào)用程序在同一源文件(同一程同一程序模塊序模塊)中,則過程可直接訪問模塊中的中,則過程可直接訪問模塊中的變量變

8、量三、通過地址表傳達(dá)變量地址三、通過地址表傳達(dá)變量地址四、通過堆棧傳送參數(shù)或參數(shù)地址四、通過堆棧傳送參數(shù)或參數(shù)地址五、多模塊之間的參數(shù)傳送五、多模塊之間的參數(shù)傳送1、通過寄存器傳送變量、通過寄存器傳送變量例例63十進(jìn)制到十六進(jìn)制數(shù)轉(zhuǎn)換程序十進(jìn)制到十六進(jìn)制數(shù)轉(zhuǎn)換程序 程序要求從鍵盤取得一個十進(jìn)制數(shù),然程序要求從鍵盤取得一個十進(jìn)制數(shù),然后把該數(shù)以十六進(jìn)制形式在屏幕上顯示后把該數(shù)以十六進(jìn)制形式在屏幕上顯示出來出來采用子程序結(jié)構(gòu):采用子程序結(jié)構(gòu):子程序子程序DECIBIN:實(shí)現(xiàn)從鍵盤取得十進(jìn)制數(shù)并把它轉(zhuǎn)換為:實(shí)現(xiàn)從鍵盤取得十進(jìn)制數(shù)并把它轉(zhuǎn)換為二進(jìn)制數(shù);二進(jìn)制數(shù);子程序子程序BINIHEX:把此二進(jìn)制數(shù)

9、以十六進(jìn)制數(shù)的形式在屏:把此二進(jìn)制數(shù)以十六進(jìn)制數(shù)的形式在屏幕上顯示出來。幕上顯示出來。子程序子程序CRLF:取得回車和換行效果:取得回車和換行效果 各子程序間用各子程序間用BX寄存器來傳送信息寄存器來傳送信息data segment ;修改修改 chr db 1bh ;修改修改data ends ;修改修改decihex segment assume cs: decihex,ds:data ;修改修改 main Proc far push ds ;修改修改 xor ax,ax push ax mov ax, data mov ds,ax ;修改修改主要部分主要部分按按ESC鍵后退出鍵后退出re

10、peat: call decibin ;十進(jìn)制到二進(jìn)制十進(jìn)制到二進(jìn)制 call crlf ;回車與換行回車與換行 call binihex ;binary to screen call crlf ;回車與換行回車與換行 CMP chr,1bH ;修改,比較修改,比較ESC碼碼 jne repeat ;修改修改 ;JMP repeat ;修改修改 ret Main endp十進(jìn)制數(shù)轉(zhuǎn)換為二進(jìn)制數(shù)十進(jìn)制數(shù)轉(zhuǎn)換為二進(jìn)制數(shù)decibin proc near mov bx, 0newchar: mov ah, 1 int 21h mov chr,al ;修改 sub al, 30h ;ASCII轉(zhuǎn) bi

11、nary jl exit cmp al,9d jg exit cbw ; AL轉(zhuǎn)字AX xchg ax, bx mov cx,10d mul cxxchg ax,bxadd bx,axjmp newcharexit:retdecibin endp2、過程和調(diào)用程序在同一源文、過程和調(diào)用程序在同一源文件件(同一程序模塊同一程序模塊)中,則過程可中,則過程可直接訪問模塊中的變量直接訪問模塊中的變量例例6.4 主程序主程序MAIN、過程、過程PROADD 主程序主程序MAIN和過程和過程PROADD在同一源在同一源文件中,要求用過程文件中,要求用過程PROADD累加數(shù)組累加數(shù)組中的所有元素,并把和中

12、的所有元素,并把和(不考慮溢出的可不考慮溢出的可能性能性)送到指定的存儲單元中去送到指定的存儲單元中去 段、數(shù)據(jù)定義段、數(shù)據(jù)定義data segment ary dw 1,2,3,4,5 ;100 dup(?);修改修改 count dw 5 ;100 修改修改 sum dw ?data endscode segment主程序主程序main proc far assume cs:code, ds:datastart: push ds ;修改修改 xor ax,ax push ax mov ax, data mov ds,ax ;修改修改 call near ptr proadd ret ;修改

13、修改main endp子程序ProaddProadd proc near ;定義子程序定義子程序 Push ax ; 保存寄存器保存寄存器 Push cx Push si Lea si, ary;取數(shù)組地址取數(shù)組地址 Mov cx, count;取數(shù)組個數(shù)取數(shù)組個數(shù) Xor ax,ax;next: add ax,si ; 數(shù)組元素依次相加數(shù)組元素依次相加 add si, 2 ;和放和放 AX loop next mov sum ,ax;結(jié)果存結(jié)果存sum pop si ; 恢復(fù)寄存器恢復(fù)寄存器 pop cx pop ax ret ;返回返回proaddendp 3、通過地址表傳達(dá)變量地址、通過

14、地址表傳達(dá)變量地址問題提出問題提出如果數(shù)據(jù)段中有兩個數(shù)組如下如果數(shù)據(jù)段中有兩個數(shù)組如下:data segment ary dw 100 dup(?) count dw 100 sum dw ? num dw 100 dup(?) n dw 100 total dw ?data ends要求分別累加要求分別累加ARY和和NUM數(shù)組的內(nèi)容,如何進(jìn)行?數(shù)組的內(nèi)容,如何進(jìn)行?解決方法解決方法 采用通過地址表傳送變量法采用通過地址表傳送變量法 把要傳送給子程序的參數(shù)都存放在地址表中把要傳送給子程序的參數(shù)都存放在地址表中 再把地址表的首地址通過寄存器再把地址表的首地址通過寄存器BX傳送到子傳送到子程序中去

15、,添加:程序中去,添加:MOV TABLE, OFFSET NUMMOV TABLE+2, OFFSET NMOV TABLE+4, OFFSET TOTALMOV BX, OFFSET TABLECALL PROADD Prog_seg segment org 100h assume CS: Prog_seg,Ds:Prog_seg,Es:Prog_segmain Proc near mov ax, prog_seg mov ds,ax mov table, offset ary mov table+2, offset count mov table+4, offset sum mov bx

16、, offset table call Proadd mov ax, 4c00h int 21hmain endp 程序程序PROADD4、通過堆棧傳送參數(shù)或參數(shù)地址、通過堆棧傳送參數(shù)或參數(shù)地址 數(shù)據(jù)定義數(shù)據(jù)定義parm_seg segment ary dw 1,2,3,4,5 ;100 dup(?);修改修改 count dw 5 ;100 ;修改修改 sum dw ?Parm_Seg endsstack_seg segment dw 100 dup(?) tos label wordstack_seg ends初始設(shè)定初始設(shè)定code1 segmentmain proc far assum

17、e cs: code1, ds: parm_seg, SS: stack_segstart: mov ax, stack_seg mov ss, ax mov sp, offset tos push ds sub ax, ax push ax 數(shù)據(jù)壓棧數(shù)據(jù)壓棧 mov ax, parm_seg ;段地址入棧段地址入棧 mov ds, ax mov bx, offset ary ; ary地址入棧地址入棧 push bx mov bx, offset count ; count地址入棧地址入棧 push bx mov bx, offset sum ; sum地址入棧地址入棧 push bx 調(diào)用

18、與返回調(diào)用與返回 call far ptr proadd Retmain endpcode1 endscode2 segment assume cs: code2proadd proc far Push bp ;保存保存 BP mov bp, sp ; 用用BP 作為基準(zhǔn)參數(shù)作為基準(zhǔn)參數(shù) push ax ;save other registers push cx push si push di mov si, bp+0ah ;取取 ary地址地址 mov di, bp+8 ; 取取 count地址地址 mov cx, di ; 取長度取長度CX - - (count) mov di, BP+6

19、 ;取取 sum地址地址 xor ax, ax ;clear AXnext: add ax, si ;compute sum add si, 2 loop next mov di,ax ;store result pop di ;restore registers pop si pop cx pop ax pop bp ret 6 ;adjust stack and returnproadd endpcode2 endsend start5.多個模塊之間的參數(shù)傳送多個模塊之間的參數(shù)傳送 自定義的符號自定義的符號 局部符號:本模塊定義與引用局部符號:本模塊定義與引用 外部符號:某個模塊中定義,另

20、一個模外部符號:某個模塊中定義,另一個模塊中引用的符號塊中引用的符號PUBLIC偽操作偽操作 格式:格式: PUBLIC symbol, 在某個模塊中定義的符號(變量、標(biāo)號、在某個模塊中定義的符號(變量、標(biāo)號、過程名等),在另一個模塊中引用過程名等),在另一個模塊中引用 必須用必須用PUBLIC 加以定義加以定義EXTRN偽操作 格式:格式: EXTRN symbol_name: type , 在另一個模塊中定義的符號(變量、標(biāo)在另一個模塊中定義的符號(變量、標(biāo)號、過程名等),在本模塊中引用號、過程名等),在本模塊中引用 必須用必須用EXTRN 加以說明加以說明 對變量,類型用對變量,類型用b

21、yte, word, dword等等 對標(biāo)號或過程名,類型用對標(biāo)號或過程名,類型用NEAR或或FAR例例6.5三模塊三模塊 模塊模塊1Extrn var2:word,lab2:farPublic var1,lab1,var4Data1 segment var1 db ? var3 dw ? var4 dw ?Data1 endsCode1 segment assume cs:code1,ds:data1Main proc farStart: Mov ax,data1 mov ds,ax Lab1: Main endpCode1 ends end start 模塊模塊2Extrn var1:by

22、te,var4:wordPublic var2Data2 segment var2 dw 0 var3 db 5 dup(?)Data2 endsCode2 segment assume cs:code2,ds:data2Main proc farStart: Mov ax,data2 mov ds,ax Main endpCode2 endsEnd模塊模塊3Extrn lab1:farPublic lab2,lab3Code3 segment assume cs:code3Main proc farStart: Mov ax,data1 mov ds,ax Lab2: Lab3: Main

23、endpCode3 endsEnd不在同一模塊參數(shù)傳送方法不在同一模塊參數(shù)傳送方法一、例一、例6.4:(:(1)外部符號定義(外部符號定義(2)使用公共數(shù)據(jù)段)使用公共數(shù)據(jù)段二、動態(tài)修改段寄存器的內(nèi)容,對外部變量所在段地二、動態(tài)修改段寄存器的內(nèi)容,對外部變量所在段地址進(jìn)行修改址進(jìn)行修改62嵌套與遞歸子程序嵌套與遞歸子程序 子程序的嵌套:一個子程序可作為調(diào)用子程序的嵌套:一個子程序可作為調(diào)用程序去調(diào)用另一個子程序程序去調(diào)用另一個子程序 遞歸調(diào)用:在子程序嵌套的情況下,如遞歸調(diào)用:在子程序嵌套的情況下,如果一個子程序調(diào)用的子程序就是它自身果一個子程序調(diào)用的子程序就是它自身 嵌套的層次不限嵌套的層次

24、不限 C CA AL LL L P PR RO OC C_ _A A R RE ET T C CA AL LL L P PR RO OC C_ _B B P PR RO OC C_ _A A R RE ET T P PR RO OC C_ _B B 主主程程序序 子子程程序序A 子子程程序序B . . . . . 增強(qiáng)功能過程定義偽操作 自學(xué)嵌套子程序的設(shè)計(jì)嵌套子程序的設(shè)計(jì) 子程序的調(diào)用和返回應(yīng)正確使用子程序的調(diào)用和返回應(yīng)正確使用CALL和和RET指令指令 要注意寄存器的保存和恢復(fù)要注意寄存器的保存和恢復(fù) 如果使用了堆棧來傳送參數(shù)等,則對堆如果使用了堆棧來傳送參數(shù)等,則對堆棧的操作要仔細(xì)考慮棧

25、的操作要仔細(xì)考慮例:習(xí)題例:習(xí)題6.4- 16進(jìn)制轉(zhuǎn)字符進(jìn)制轉(zhuǎn)字符(堆棧使用)(堆棧使用)stack segment at 500h dw 128dup(?) tos label word sum dw ?stack endscode segmentmain proc far assume cs: code, SS: start: mov ax, stack mov ss, ax mov sp, offset tos push ds sub ax, ax push ax mov ax, 4321h call htoa first: retmain endphtoa proc near cmp

26、ax,15 jle BL push ax push bp mov bp, sp mov bx,bp+2 and bx,000fH mov bp+2,bx pop bp mov cl,4 shr ax,cl call htoa second: pop axb1: add al,30h cmp al,3ah jl printit add al,7hprintit: mov al,dl mov ah,2 int 21h ret htoa endpcode endsend start 63子程序舉例子程序舉例 例例6.9:HEXIDEC是一個把十六進(jìn)制數(shù)是一個把十六進(jìn)制數(shù)轉(zhuǎn)換成十進(jìn)制數(shù)的程序。要求把從

27、鍵盤轉(zhuǎn)換成十進(jìn)制數(shù)的程序。要求把從鍵盤輸入的輸入的0FFFFH的十六進(jìn)制正數(shù)轉(zhuǎn)換為的十六進(jìn)制正數(shù)轉(zhuǎn)換為十進(jìn)制數(shù)并從屏幕上顯示出來十進(jìn)制數(shù)并從屏幕上顯示出來子程序組成子程序組成 :HEXIBIN:十六進(jìn)制轉(zhuǎn)二進(jìn)制:十六進(jìn)制轉(zhuǎn)二進(jìn)制BINIDEC:二進(jìn)制轉(zhuǎn)十進(jìn)制:二進(jìn)制轉(zhuǎn)十進(jìn)制1、分析、分析 2、程序組成、程序組成 hexidec segment ;代碼段代碼段main proc far ;主過程主過程 assume cs:hexidecstart: push ds sub ax,ax push ax call hexibin ;鍵盤輸入,鍵盤輸入,十六進(jìn)制轉(zhuǎn)二進(jìn)制十六進(jìn)制轉(zhuǎn)二進(jìn)制 call cr

28、lf ;回車換行回車換行 call binidec ;二進(jìn)制轉(zhuǎn)十進(jìn)制二進(jìn)制轉(zhuǎn)十進(jìn)制 call crlf ;回車換行回車換行 ret ;返回返回 DOSmain endp hexibin proc near mov bx, 0 ;二進(jìn)制結(jié)果放二進(jìn)制結(jié)果放BX,初始化,初始化0newChar: mov ah, 1 ;鍵盤輸入鍵盤輸入 int 21h sub al, 30h ;將將ASCII 轉(zhuǎn)化為轉(zhuǎn)化為 binary jl exit ;jump: if 9d ? jl addto ;yes, 是數(shù)字,否則可能是字母是數(shù)字,否則可能是字母 sub al, 27h ;將將ASCII 轉(zhuǎn)化為轉(zhuǎn)化為 binary cmp al, 0ah ;is it 0fH? (小寫字母小寫字母f) jge exit ;yes,不是字母,否則是小寫字母不是字母,否則是小寫字母addto: mov Cl, 4 ;移動移動4位位 shl bx,cl mov ah, 0 add bx,

溫馨提示

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

評論

0/150

提交評論