




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 商业数据安全法律援助与处理合同
- 职业技能培训项目合作研发实施协议
- 小产权房居住权分割与共有权变更及租赁合同协议
- 跨界合作授权独家补充协议书
- 跨国合作影视广告制作与全球市场推广服务协议
- 医疗查房车租赁及智能设备维护保养合同
- 游艇码头泊位租赁及船舶租赁与维修保养服务合同
- 共有产权住房离婚份额分割与财产清算协议
- 国际物流货物追踪与客户满意度提升服务合同
- 网络内容审核办公场地租赁及广告位合作合同
- 厂内运输车辆专项安全检查表
- 企业商学院的组织架构和培训体系架构
- 铁道机车-机车检修运用
- 安全操作规程培训课件
- DL∕T 547-2020 电力系统光纤通信运行管理规程
- 切尔诺贝利核电站事故工程伦理分析
- (无线)门禁系统报价单
- 社会工作介入老年社区教育的探索
- 国开电大-工程数学(本)-工程数学第4次作业-形考答案
- 高考倒计时30天冲刺家长会课件
- 施工项目现金流预算管理培训课件
评论
0/150
提交评论