第6章子程序結構_第1頁
第6章子程序結構_第2頁
第6章子程序結構_第3頁
第6章子程序結構_第4頁
第6章子程序結構_第5頁
已閱讀5頁,還剩53頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

1、第第6章子程序結構章子程序結構本章重點本章重點 1)子程序的概念、基本結構形式、子程序)子程序的概念、基本結構形式、子程序的現場保護和恢復及子程序的調用和返的現場保護和恢復及子程序的調用和返回回2)子程序設計的步驟和方法)子程序設計的步驟和方法3)主程序和子程序間傳遞參數的三種方法)主程序和子程序間傳遞參數的三種方法4)常用)常用DOS系統功能調用系統功能調用 61 子程序的設計方法子程序的設計方法 過程定義偽操作過程定義偽操作 子程序的調用和返回子程序的調用和返回 保存與恢復寄存器保存與恢復寄存器 子程序的變量傳送子程序的變量傳送 增強功能的過程定義偽操作增強功能的過程定義偽操作6.1.1

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

3、的標識符,它又是子程序入口的符號地址符號地址 一般,主過程一般,主過程N應定義為應定義為FAR屬性屬性例:調用程序和子程序在同一代碼段中例:調用程序和子程序在同一代碼段中 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調用程序和子程序不在同一個代碼段內調用程序和子程序

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

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

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

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

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

9、以十六進制數的形式在屏:把此二進制數以十六進制數的形式在屏幕上顯示出來。幕上顯示出來。子程序子程序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 ;十進制到二進制十進制到二進制 call crlf ;回車與換行回車與換行 call binihex ;binary to screen call crlf ;回車與換行回車與換行 CMP chr,1bH ;修改,比較修改,比較ESC碼碼 jne repeat ;修改修改 ;JMP repeat ;修改修改 ret Main endp十進制數轉換為二進制數十進制數轉換為二進制數decibin proc near mov bx, 0newchar: mov ah, 1 int 21h mov chr,al ;修改 sub al, 30h ;ASCII轉 bi

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

12、的所有元素,并把和(不考慮溢出的可不考慮溢出的可能性能性)送到指定的存儲單元中去送到指定的存儲單元中去 段、數據定義段、數據定義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;取數組地址取數組地址 Mov cx, count;取數組個數取數組個數 Xor ax,ax;next: add ax,si ; 數組元素依次相加數組元素依次相加 add si, 2 ;和放和放 AX loop next mov sum ,ax;結果存結果存sum pop si ; 恢復寄存器恢復寄存器 pop cx pop ax ret ;返回返回proaddendp 3、通過地址表傳達變量地址、通過

14、地址表傳達變量地址問題提出問題提出如果數據段中有兩個數組如下如果數據段中有兩個數組如下:data segment ary dw 100 dup(?) count dw 100 sum dw ? num dw 100 dup(?) n dw 100 total dw ?data ends要求分別累加要求分別累加ARY和和NUM數組的內容,如何進行?數組的內容,如何進行?解決方法解決方法 采用通過地址表傳送變量法采用通過地址表傳送變量法 把要傳送給子程序的參數都存放在地址表中把要傳送給子程序的參數都存放在地址表中 再把地址表的首地址通過寄存器再把地址表的首地址通過寄存器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、通過堆棧傳送參數或參數地址、通過堆棧傳送參數或參數地址 數據定義數據定義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初始設定初始設定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 數據壓棧數據壓棧 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 調用

18、與返回調用與返回 call far ptr proadd Retmain endpcode1 endscode2 segment assume cs: code2proadd proc far Push bp ;保存保存 BP mov bp, sp ; 用用BP 作為基準參數作為基準參數 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.多個模塊之間的參數傳送多個模塊之間的參數傳送 自定義的符號自定義的符號 局部符號:本模塊定義與引用局部符號:本模塊定義與引用 外部符號:某個模塊中定義,另

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

21、yte, word, dword等等 對標號或過程名,類型用對標號或過程名,類型用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不在同一模塊參數傳送方法不在同一模塊參數傳送方法一、例一、例6.4:(:(1)外部符號定義(外部符號定義(2)使用公共數據段)使用公共數據段二、動態修改段寄存器的內容,對外部變量所在段地二、動態修改段寄存器的內容,對外部變量所在段地址進行修改址進行修改62嵌套與遞歸子程序嵌套與遞歸子程序 子程序的嵌套:一個子程序可作為調用子程序的嵌套:一個子程序可作為調用程序去調用另一個子程序程序去調用另一個子程序 遞歸調用:在子程序嵌套的情況下,如遞歸調用:在子程序嵌套的情況下,如果一個子程序調用的子程序就是它自身果一個子程序調用的子程序就是它自身 嵌套的層次不限嵌套的層次

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 . . . . . 增強功能過程定義偽操作 自學嵌套子程序的設計嵌套子程序的設計 子程序的調用和返回應正確使用子程序的調用和返回應正確使用CALL和和RET指令指令 要注意寄存器的保存和恢復要注意寄存器的保存和恢復 如果使用了堆棧來傳送參數等,則對堆如果使用了堆棧來傳送參數等,則對堆棧的操作要仔細考慮棧

25、的操作要仔細考慮例:習題例:習題6.4- 16進制轉字符進制轉字符(堆棧使用)(堆棧使用)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是一個把十六進制數是一個把十六進制數轉換成十進制數的程序。要求把從

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

28、lf ;回車換行回車換行 call binidec ;二進制轉十進制二進制轉十進制 call crlf ;回車換行回車換行 ret ;返回返回 DOSmain endp hexibin proc near mov bx, 0 ;二進制結果放二進制結果放BX,初始化,初始化0newChar: mov ah, 1 ;鍵盤輸入鍵盤輸入 int 21h sub al, 30h ;將將ASCII 轉化為轉化為 binary jl exit ;jump: if 9d ? jl addto ;yes, 是數字,否則可能是字母是數字,否則可能是字母 sub al, 27h ;將將ASCII 轉化為轉化為 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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論