




已阅读5页,还剩39页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
在程序设计中,可以发现一些多次无规律重复的程序段或语句序列。解决此类问题一个行之有效的方法就是将它们设计成可供反复调用的独立的子程序结构,以便在需要时调用。在汇编语言中,子程序又称过程。 调用子程序的程序称为主调程序或主程序。,第6章 子程序结构,子程序的基本结构包括以下几个部分: (1)子程序定义 (2)保护现场和恢复现场 (3)子程序体 (4)子程序返回,子程序的结构,子程序的定义是由过程定义伪指令PROC和ENDP来完成的。其格式如下: 过程名 PROC NEAR/FAR 过程名 ENDP 其中PROC表示过程定义开始,ENDP表示过程定义结束。过程名是过程入口地址的符号表示。 一般过程名同标号一样,具有三种属性,即段属性、偏移地址属性以及类型属性(NEAR 和 FAR)。,6.1.1 子程序的定义,6.1 子程序的设计方法,1.如果调用程序和过程在同一代码段中,则使用NEAR属性;,MAIN PROC FAR CALL SUBR1 RET MAIN ENDP ; SUBR1 PROC NEAR RET SUBR1 ENDP,MAIN PROC FAR CALL SUBR1 RET SUBR1 PROC NEAR RET SUBR1 ENDP MAIN ENDP,例6.1,过程嵌套定义,2. 如果调用程序和过程不在同一代码段中,则使用FAR属性;,SEGX SEGMENT SUBT PROC FAR RET SUBT ENDP CALL SUBT SEGX ENDS ; SEGY SEGMENT CALL SUBT SEGY ENDS,例6.2,6.1.2 子程序的调用和返回,调用: CALL far/near ptr 过程名,返回: RET n,6.1.3 保护现场和恢复现场,例如:若子程序PROG中改变了寄存器AX,BX,CX,DX的值,则 可采用如下方法保护和恢复现场。 PROG PROC PUSH AX PUSH BX PUSH CX ;保护现场 PUSH DX POP DX POP CX POP BX ;恢复现场 POP AX RET ;返回断点处 PROC ENDP,6.1.4 主程序与子程序参数传递方式,1 通过寄存器传送参数 这是最常用的一种方式,使用方便,但参数很多时不能使用这种方法。 例6.3 十进制到十六进制转换的程序。程序要求从键盘取得一个十进制数,然后把该数以十六进制的形式在屏幕上显示出来。,开始,调用DECIBIN,调用CRLF,调用BINIHEX,调用CRLF,结束,从键盘取得十进制 数,保存到BX中,显示回车和换行,用十六进制形式 显示BX中的数,Decihex segment assume cs:Decihex Main proc far Repeat: push ds xor ax, ax push ax call decibin call crlf call binihex call crlf ret Main endp,Decibin proc near mov bx, 0 Newchar: mov ah, 1 int 21h sub al, 30h jl exit cmp al, 9 jg exit cbw xchg ax, bx mov cx, 10 mul cx xchg ax, bx ;每次乘的 add bx, ax ;结果在BX中 jmp newchar Exit : ret Decibin endp,Binihex proc near mov ch, 4 Rotate: mov cl, 4 rol bx, cl mov dl, bl and dl, 0fh add dl, 30h cmp dl, 3ah jl print add dl, 7h Print: mov ah, 2 int 21h dec ch jnz rotate ret Binihex endp,Crlf proc near mov ah, 2 mov dl, odh int 21h mov dl, oah int 21h ret Crlf endp Decihex ends end repeat,如果过程和调用过程在同一源文件(同一模块)中,则过程可直接访问模块中的变量。 例 6.4_1 主程序MAIN和过程PROADD在同一源文件中,要求用过程PROADD累加数组的所有元素,并把和(不考虑溢出的可能性)送到指定的存储单元中去,DATA SEGMENT ARY DW 100 DUP (?) COUNT DW 100 SUM DW ? DATA ENDS CODE SEGMENT MAIN PROC FAR ASSUME CS:CODE , DS:DATA START: PUSH DS SUB AX ,AX PUSH AX MOV AX , DATA CALL NEAR PTR PROADD RET MAIN ENDP,PROADD PROC NEAR PUSH AX PUSH CX PUSH SI PUSH DI LEA SI ,ARY MOV CX ,COUNT XOR AX , AX NEXT: ADD AX , SI ADD SI , 2 LOOP NEXT MOV SUM , AX POP DI POP SI POP CX POP AX RET PROADD ENDP CODE ENDS END START,CODE SEGMENT ARY DW 100 DUP(?) COUNT DW 100 SUM DW ? NUM DW 100 DUP (?) N DW 100 TOTAL DW ? MOV TABLE , OFFSET ARY MOV TABLE+2, OFFSET COUNT MOV TABLE+4 , OFFSET SUN MOV BX , OFFSET TABLE CALL PROADD ;计算SUM ,PROADD PROC NEAR PUSH AX PUSH CX PUSH SI PUSH DI PUSH SI,BX MOV DI , BX+2 MOV CX , DI MOV DI , BX+4 XOR AX , AX NEXT: ADD AX , SI ADD SI , 2 LOOP NEXT MOV 【DI, AX POP DI POP SI POP CX POP AX RET PROADD ENDP CODE ENDS END START,3 通过地址表传递参数,例6.4_2,4 通过堆栈传递地址或参数,Data segment Ary dw 100 dup(?) Count db 100 Sum dw ? Data ends Stack segment para stack stack dw 100 dup(?) tos label word Stack ends Code1 segment assume cs:code1, ds:data, ss;stack Main proc far Start: push ds xor ax, ax push ax mov ax, data mov ds, ax,mov ax,stack mov ss, ax mov sp,offset tos Mov bx, offset ary Push bx Mov bx, offset count Push bx Mov bx, offset sum Push bx Call far ptr proadd mov al, sum mov dl, al mov ah, 2 int 21h ret Main endp Code1 ends,例6.4_3,Sum地址 Count地址 Ary地址,sp,di si cx ax bp,(Sp)bp,IP CS,Code2 segment assume cs:code2 Proadd proc far push bp mov bp, sp push ax push cx push si push di mov si, bp+0ah mov di, bp+08h mov cl, di mov di, bp+06h xor al, al Again: add al, si inc si dec cl jnz again mov di, al pop di pop si pop cx,pop ax pop bp ret 6 Proadd endp Code2 ends end start,bp+0ah,bp+08h,bp+06h,Sp,Sp,Sp,Sp,Sp,(1) PUBLIC伪指令 格式:PUBLIC 符号 ,符号 功能:说明其后的符号是全局符号。全局符号能被其他模块引用。(局部符号) (2) EXTRN伪指令 格式:EXTRN 符号:类型 ,符号:类型 功能:说明在本模块中需要引用的、由其他模块定义的符号,即外部符号。,5 多个模块之间的参数传送问题,; source module 1 extrn var2:word,lab2:far public var1,lab1 Data1 segment var1 db ? var3 dw ? var4 dw ? Data1 ends code1 segment assume cs:code1,ds:data1 Main proc far start: mov ax , data1 mov ds,ax lab1: mov ah,4ch int 21h Main endp Code1 ends End start,; source module 2 extern var1:byte,var4:word public var2 Data2 segment var2 dw ? var3 dw ? Data2 ends code2 segment assume cs:code2,ds:data2 Main proc far start: mov ax , data2 mov ds,ax mov ah,4ch int 21h Main endp Code2 ends End start,注意:应先有public 定义,然后才有extrn说明,; source module 3 extern lab2: far public lab2,lab3 Data2 segment var2 dw ? var3 dw ? Data2 ends code3 segment assume cs:code3 Lab2: Lab3: Code3 ends End,例6.5 多个模块间的参数共享,;Source model 1 EXTERN proadd: far DATA SEGMENT common ARY DW 100 DUP (?) COUNT DW 100 SUM DW ? DATA ENDS CODE1 SEGMENT MAIN PROC FAR ASSUME CS:CODE1 , DS:DATA START: PUSH DS SUB AX ,AX PUSH AX MOV AX , DATA CALL far ptr PROADD RET MAIN ENDP CODE1 ENDS END START,主程序和子过程不在同一个模块的时参数传递方法一,LOOP NEXT: MOV SUM , AX POP DI POP SI POP CX POP AX RET PROADD ENDP CODE2 ends END,;Source model 2 PUBLIC PROADD DATA SEGMENT common ARY DW 100 DUP (?) COUNT DW 100 SUM DW ? DATA ENDS CODE2 SEGMENT PROADD PROC FAR ASSUME CS:CODE2 , DS:DATA MOV AX,DATA MOV DS,AX PUSH AX PUSH CX PUSH SI PUSH DI LEA SI, ARY MOV CX, COUNT XOR AX, AX NEXT: ADD AX, SI ADD SI, 2,(如例6.4_1的参数传递可利用段覆盖),;Source model 1 extern var1 : word extern output: far extern var2 : word public quit local_data segment var dw 5 local_data ends code segment assume cs:code,ds:local_data main proc far start: mov ax,local_data mov ds,ax mov bx,var mov ax,seg var1 mov es,ax add bx,es:var1,主程序和子过程不在同一个模块的时参数传递方法二, mov ax,seg var2 mov es,ax sub es:var2,50 jmp ouput quit:mov ah,4ch int 21h main endp code ends end start ;Source model 2 public var1 extdata1 segment var1 dw 10 extdata1 ends end,;source model 3 public var2 extern quit: far extdata2 segment var2 dw 3 extdata2 ends public output program segment assume cs:program, ds:extdata2 output: jmp quit program ends end,(例6.6 含三个源模块),;Source model 1 Global segment public Extern var1:word Extern var2:word Global ends Local_data segment Local_data ends code segment assume cs:code, ds: local_data, es:global main proc far,主程序和子过程不在同一个模块的时参数传递方法三,start: mov x,local_data mov ds,ax mov ax, global mov es,ax mov bx,es:var1 add es:var2,bx mov ah,4ch int 21h main endp code ends end start,(例6.7 含二个源模块),;source model 2 Global segment public public var1 public var2 var1 dw ? var2 dw ? Global ends end,6.1.5 增强功能的过程定义伪操作,Procname PROC attributes field USER register list ,parameter field Procname ENDP Attributes field(属性字段)包括: Distance : near 、far Language type :说明是那种高级语言的子程序 如pascal 、c 等。 Visibility : 说明程序的可见性 是private 或是public。 Prologue :是一个宏的名字,允许用宏来控制过程的入口或出口有关的代码 USER:该字段用来指定用户所需保存和恢复的寄存器表。 Parameter field: 参数字段 ,允许用户指定该过程所用的参数 。 标识符:类型,标识符:类型,Data segment Ary db 10 dup(?) Count db 10 Sum db ? Data ends Stack segment para stack stack db 100 dup(?) Stack ends Code1 segment assume cs:code1, ds:data, ss:stack Main proc far Start: push ds xor ax, ax push ax mov ax, data mov ds, ax,Mov bx, offset ary Push bx Mov bx, offset count Push bx Mov bx, offset sum Push bx Call far ptr proadd mov al, sum mov dl, al mov ah, 2 int 21h ret Main endp Code1 ends,对例6.4 采用用增强功能过程定义伪操作实现,Code2 segment assume cs:code2 Proadd proc far push bp mov bp, sp push ax push cx push si push di mov si, bp+0ah mov di, bp+08h mov cl, di mov di, bp+06h xor al, al Again: add al, si inc si dec cl jnz again mov di, al pop di pop si pop cx pop ax pop bp ret 6 Proadd endp Code2 ends end start,Code2 segment assume cs:code2 Proadd proc pascal user ax cx si di , para:word,parc:word,pars:word mov si, para mov di, parc mov cl, di mov di, pars xor al, al Again: add al, si inc si dec cl jnz again mov di, al ret Proadd endp Code2 ends end start,Sum地址 Count地址 Ary地址,(bp),IP CS,( bp +2),( bp +4),( bp +6),( bp +8),( bp +a),原始bp,pars,para,parc,局部变量,di si cx ax,( bp -2),Code2 segment assume cs:code2 Proadd proc far push bp mov bp, sp push ax push cx push si push di mov si, bp+0ah mov di, bp+08h mov cl, di mov di, bp+06h xor al, al Again: add al, si inc si dec cl jnz again mov di, al pop di pop si pop cx pop ax pop bp ret 6 Proadd endp Code2 ends end start,Code2 segment assume cs:code2 Proadd proc C user ax cx si di , pars:word,parc:word,para:word mov si, para mov di, parc mov cl, di mov di, pars xor al, al Again: add al, si inc si dec cl jnz again mov di, al ret Proadd endp Code2 ends end start,Sum地址 Count地址 Ary地址,(bp),IP CS,( bp +2),( bp +4),( bp +6),( bp +8),( bp +a),原始bp,pars,para,parc,局部变量,di si cx ax,( bp -2),增强功能的过程定义伪操作除了以上功能外 ,还可以在过程中定义局部变量。局部变量是在过程内部使用的变量,他是在过程调用是在堆栈中建立的,在退出过程是被释放。 可以用 LOCAL 定义 LOCAL 变量:类型,变量:类型,Sum地址 Count地址 Ary地址,(bp),IP CS,( bp +2),( bp +4),( bp +6),( bp +8),( bp +a),原始bp,( bp -2),( bp -4),局部变量,例6.8 编程把以ASCII形式表示的十进制数转换为二进制数,.model small .386 .stack 200h .data Ascval db 12345 Binval dw ? .code Main proc far Start: mov ax,data mov ds,ax, lea bx,asval push bx lea bx,binval push bx call convaxbin mov ah,4ch int 21h Main endp,Convascbin proc pascal uses ax,bx,cx,dx,si,di,par1:word,par2:word Local asclen:word,mulfact:word mov bx,10 mov si,par1 mov di,par2 sub di,si mov asclen,di mov cx,asclen add si,asclen dec si mov mulfact,1 mov di,par2 mov di,0 Next: mov al,si and ax,000fh,Mul mulfact Add di,ax Mov ax,mulfact Mul bx Mov mulfact,ax Dec si Loop next Ret Convascbin endp end main,push bp mov bp,sp add sp,0fch push ax push bx push cx push dx push si push di mov bx,oah mov si,bp+6 mov di,bp+4 sub di,si mov bp2】,di mov cx,bp-2 add si,bp-2 dec si mov word ptr bp-2,0001 mov di,bp+4 mov word ptr di,0,例6.8 经过汇编后的Convascbin子过程程序,next : mov al,si and ax,000fh mul word ptr bp-4 add di ,ax mov ax,bp-4 mul bx mov bp-4, ax dec si loop next pop di pop si pop dx pop cx pop bx pop ax mov sp,bp pop bp ret 0004,6.2 子程序的嵌套 一个子程序可以作为调用程序去掉用另一个子程序,这种情况称为子程序的嵌套。嵌套深度不限。但应注意的问题是堆栈的溢出:上溢、下溢 递归子程序:如果一个子程序调用的是子程序的本身,就是递 归子程序。,例 计算 N!=N*(N-1)*(N-2)* *1 -递归子程序,Data segment Num db 3 Result dw ? Data ends Stack segment para stack stack db 100 dup(?) tos label word Stack ends Code segment assume cs:code, ds:data, ss:stack Main proc far Begin: push ds xor ax, ax push ax mov ax, data mov ds, ax,mov ax,stack mov ss,ax mov sp, offset tos mov ah, 0 mov al, num call factor mov result, ax ret Main endp,Factor proc push ax sub ax, 1 jne f_cont pop ax jmp return f_cont: call factor pop cx mul cl return: ret factor endp Code ends end begin,IP1,Mov result, ax 地址,3,IP2,Pop cx 地址,2,IP3,Pop cx 地址,1,ax =1,IP POP CX 地址,cx =2,ax*cx =1*2,IP POP CX 地址,cx =3,ax*cx =1*2*3,IP Mov result, ax 地址,常用的DOS系统功能调用,1单字符输入(1号调用) 2单字符显示(2号调用) 3打印输出(5号调用) 4结束调用(4CH号调用) 5显示字符串(9号调用) 6字符串输入(10号调用),1单字符输入(1号调用) 格式:MOV AH,1 INT 21H 功能:从键盘输入字符的ASCII码送入寄存器AL中,并送显示器显示。 2单字符显示(2号调用) 格式:MOV DL,待显示字符的ASCII码 MOV AH,2 INT 21H 功能:将DL寄存器中的字符送显示器显示.,3打印输出(5号调用) 格式:MOV DL,待打印字符的ASCII码 MOV AH,5 INT 21H 功能:将DL寄存器中的字符送打印机打印。 4结束调用(4CH号调用) 格式:MOV AH,4CH INT 21H 功能:终止当前程序并返回调用程序。,5显示字符串(9号调用) 格式:LEA DX,待显示字符串首偏移地址 MOV AH,9 INT 21H 功能:将当前数据区中以结尾的字符串送显示器显示。 6字符串输入(10号调用) 格式:LEA DX,缓冲区首偏移地址 MOV AH,10 INT 21H 功能:从键盘上输入一字符串到用户定义的输入缓冲区中,并送显示器显示。,maxlen db 32 actlen db ? string db 32 dup(?),lea dx , maxlen mov ah,0ah int 21h,说明:缓冲区的第一个字节保存最大字符数,这个最 大字符数由用户程序给出。如果键入的字符数 比此数大,机器发出嘟嘟声。第二个字节存放 实际输入的字节数,这个不是由用户填入的而 由功能A填入的。在这两个字节之后,才是我们 输入的字符串。,6.3 子程序举例,例1:HEXIDEX是一个十六进制数转换成十进制数的程序。要求把从键盘输入的0 FFFFH的十六进制正数转换为十进制数并在屏幕上显示出来。,Display equ 2h Key equ 1h Doscall equ 21h Hexidec segment Main proc far assume cs:hexidec Start: push ds sub ax,ax push ax call hexidec call crlf call binidec call crlf jmp main ret main endp,Crlf proc near mov dl ,0ah mov ah,display int boscall mov dl,0dh mov ah,display int doscall ret crlf endp Hexidec ends end start,Hexidec proc near mov bx ,0 Newchar: mov key_in int doscall sub al,30h jl exit cmp al, 10d jl add_to sub al ,27h cmp al,0ah jl exit cmp ah,10h jge exit Add_to: mov cl ,4 shl bx , cl mov ah ,0 add bx,ax jmp Exit: Ret Hexidec endp,Binidec proc near mov cx , 10000d call dec_div mov cx , 1000d call dec_div mov cx,100d call dec_div mov cx,10d call dec_div mov cx,1d call dec_div ret Dec_div proc near mov ax, bx mov dx ,0 div cx mov bx,dx mov dl,al add dl,30h mov ah,display int doscall,ret dec_div endp Binidec endp,例2:一个简单的信息检索系统。在数据区里,有10个不同的信息,编号为09,每个信息包括30个字符。现在要编制一个程序:从键盘接收09之间的一个编号,然后在屏幕上显示相应编号的信息的内容。,Datarea segment thirty db 30 msg0 db 0 I like my IBM-PC- msg1 db 1 I like my IBM-PC- msg2 db 2 I like my IBM-PC- msg3 db 3 I like my IBM-PC- msg4 db 4 I like my IBM-PC- msg5 db 5 I like my IBM-PC- msg6 db 6 I like my IBM-PC- msg7 db 7 I like my IBM-PC- msg8 db 8 I like my IBM-PC- msg9 db 9 I like my IBM-PC- errmsg db error! Invalid praameter Datarea ends,Stack segment db 256 dup(0) tos lable word Stack ends Prognam segment assume cs:prognam ,ds:datarea,ss:stack Start: push ds xor ax,ax push ax mov ax,stack mov ss,ax mov ax,datarea mov ds,ax mov sp,offset tos Begin:mov ah,1 int 21h sub al,0 jc error cmp al, 9 ja error,Mov bx,offset msg0 Mul thirty Add bx,ax Call display Jmp begin Error: mov bx,offset errmsg call display ret Display proc near mov cx,30 mov dl,bx call dispchar inc bx loop disp1 mov dl,0dh call dispchar mov dl,0ah call dispchar ret Dispchar endp,Dispchar proc naer mov ah,2 int 21h ret Dispchar endp Main endp Prognam ends End start,例3:人名排序程序。先从终端键入最多30个人名,当所有人名都进入后,按字母上升的次序将人名排序,并在屏幕上显示已经排好的人名。,Data segment namepa
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 上饶预制化粪池施工方案
- 卸车指挥工设备维护与保养考核试卷及答案
- 中药灸熨剂工三级安全教育(班组级)考核试卷及答案
- 药械科不良安全事件培训课件
- 信息传播策略优化分析报告
- 2025版司法局《涉嫌抢劫罪的法律意见书》(空白模板)
- 精密过滤器施工方案
- 门面装饰工程施工方案
- 咨询公司项目规划方案
- 城市建筑纸浆配送方案设计
- 2025年年公租房租赁合同范本
- 脊柱骨科课件教学
- 物业服务培训课件大纲
- 2025至2030中国原果浆行业项目调研及市场前景预测评估报告
- 家庭教育指导行业2025年市场规模与增长趋势报告
- 商场装修合同
- 急性腹泻病教学课件
- 2025年版住宅房屋租赁合同范本下载
- 2-5跨学科实践制作隔音房间模型八年级物理学案人教版
- 房屋学位租赁合同协议书
- 2025年高速公路标杆企业组织效能报告
评论
0/150
提交评论