汇编语言第5章王爽版(子程序调用指令)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
POP CX
POP BX POP AX RET PROG ENDP
二、主程序与过程的参数传递方式
主程序-子程序的参数传递: 入口参数—— 也称入口条件,是指主程序调用子程序 前,为子程序内部数据处理准备所需的预置值;
出口参数—— 也称出口条件,是子程序返回主程序后, 把子程序处理的结果传递给主程序的数据。
第5章
结构化程序设计
教学基本内容
5.1 子程序的概念 5.2 子程序的定义、调用和返回 ** 5.3 子程序的现场保护与参数传递** 5.4 子程序设计 *
5.5 子程序的嵌套与递归调用
5.6 宏汇编程序设计
5.1 子程序的概念
1、子程序:在程序设计中,我们会发现一些多次无规律重复的 程序段或语句序列。解决此类问题一个行之有效的方法就是将 它们设计成可供反复调用的独立的子程序结构,以便在需要时 调用。在汇编语言中,子程序又称过程。 过程(子程序):是指功能相对独立的一段程序。
;子程序定义 ;返回
子程序结构示例
1.多处调用完成同一功能的子 程序: code SEGMENT start: … CALL sub … CALL sub … MOV AH, 4CH INT 21H sub PROC 、、 、、 RET sub ENDP code ENDS end start
2.模块化程序设计:多个子程序的调用
DATA SUM D1 D2 DATA STACK
STACK CODE START:
CODE
SEGMENT 通过变量传送 DB 0 DB ? DB ? ENDS SEGMENT DB 100 DUP(?) ENDS SEGMENT ASSUME DS:DATA,SS:STACK,CS:CODE MOV AX,DATA SPROG PROC MOV DS,AX MOV AL, D1 MOV D1, 1 ADD AL, D2 MOV D2, 2 OR AL, 30H CALL SPROG MOV SUM, AL MOV AH,4ch MOV dl,al INT 21H MOV ah,2 ENDS INT 21h END START RET SPROG ENDP END START
子程序名
子程序名
PROC [NEAR/FAR]
┆ ENDP ;过程体
解释:(1)子程序名是子程序入口地址的符号表示。同标号一 样,具有三种属性,即段属性、偏移地址属性以及类型属性。
(2)PROC表示子程序定义开始,ENDP表示子程序定义结束。
(3) NEAR/FAR
2、子程序的调用和返回 过程定义后,可在主程序中用CALL指令,反复调用。 过程结束,由返回指令RET返回主程序。
Call
add64 mov ah,4ch int 21h main endp ;主程序结束
;子过程ADD64开始 add64 proc push bp ; mov bp,sp push bx push si push di push cx pushf ;保存现场 mov si,[bp+4] ; mov bx,[bp+6] mov di,[bp+8] mov cx,[bp+10] ;读取参数 cld
例5-2:多字节数相加的程序(寄存器传递过程参数)
data num1 num2 len data stack
segment db 01h,02h,03h,04h,05h,06h db 0ffh,07h,0ffh,03h,01h,06h equ $- num2 ends segment stack dw 100 dup(?) stack ends code segment assume cs:code,ds:data,ss:stack
5、子程序的书写形式 例: NEAR 类型子程序 code SEGMENT … CALL subp xor ax,ax
… mov ah,4ch int 21h
;code段 ;调用指令 ,xor指令的地址入栈
PROC NEAR … RET subp ENDP code ENDS END START
subp
子程序返回指令(RET)
放在子程序的末尾,它使子程序在执行完任务后将堆栈中的 断点弹出,控制程序返回主程序继续执行被打断的程序。而 返回地址(断点)就是子程序调用时入栈保护的断点地址IP (段内调用)或IP和CS值(段间调用)。通常,RET指令的类 型是隐含的,它自动与子程序定义时的类型相匹配,如果是 段内,返回时将栈顶的一个字弹给IP寄存器;如为段间,返 回时先从栈顶弹出一个字给IP,接着再弹出一个字给CS。但 是,当采用间接调用时,必须注意:保证CALL指令的类型与 过程中RET指令的类型匹配,以免发生错误。例如CALL WORD PTR[BX]只能是段内调用,而CALL DWORD PTR[BX]能够调用 一个远过程(段间调用),这样RET才能够识别返回类型。
;主程序为过程 MAIN PROC FAR push ds xor ax,ax push ax mov ax,data mov ds,ax mov es,ax mov ax,len/2 push ax mov ax,offset buffer push ax mov ax,offset va11 push ax mov ax,offset va12 push ax
Start: mov ax,data mov ds,ax
lea si,num1 lea di,num2 mov cx,len
call mpadd
mov ah,4ch int 21h
Mpadd proc push ax push cx push si push di jcxz exit clc Next: mov al,[di] adc [si],al inc si inc di loop next Exit: pop di pop si pop cx pop ax ret Mpadd endp Code ends end start
演示
5.2 子程序的定义、调用和返回(续)
子程序调用指令(CALL)
CALL指令分成4种类型 CALL子程序名 CALL r16/m16 CALL far ptr子程序 CALL far ptr mem ;段内直接调用 ;段内间接调用 ;段间直接调用 ;段间间接调用
CALL指令需要保存返回地址: – 段内调用——偏移地址IP入栈 SP←SP-2,SS:[SP]←IP – 段间调用——偏移地址IP和段地址CS入栈 SP←SP-2,SS:[SP]←CS SP←SP-2,SS:[SP]←IP
子程序返回指令(RET)
RET [n] 功能:弹出CALL指令压入堆栈的返回地址
– 段内返回——偏移地址IP出栈 IP←SS:[SP], SP←SP+2
– 段间返回——偏移地址IP和段地址CS出栈 IP←SS:[SP],SP←SP+2 CS←SS:[SP],SP←SP+2
注意:在使用CALL和RET时,要保证过程的正确调用和返回 说明: RET可以带参数
例5-3多字数相加的程序(堆栈传递子程序参数) RET指令中参数的应用例子
data va11 va12 buffer len data stack
segment dw 9898h,7676h,5454h,3232h ;被加数 dw 9898h,7676h,5454h,3232h ;加数 dw 4 dup(?) ;和 equ $-buffer ends segment stack dw 100 dup(?) stack ends code segment assume cs:code,ds:data,ss:stack,es:data
ENDS END begin
子程序的位置通常在主程序的所有可 执行指令之前或之后,不能放在主程 序的可执行指令序列内部,否则会破 坏主程序结构
5.3子程序的现场保护与参数传递
PROG PROC PUSH AX
一、信息的保护与恢复
PUSH BX
PUSH CX PUSH DX ┆ POP ┆ DX ;保护现场 例如:若子程序PROG中 改变了寄存器AX,BX, CX,DX的值,则可采用 此方法保护和恢复现场。 ;恢复现场 ;返回断点处
例5-1:分别用三种参数传递方法编写求1+2的和的程 序。要求将结果送到内存单元,并显示。
DATA SUM DATA STACK STACK CODE START:
CODE
SEGMENT 通过寄存器传送 DB 0 ENDS SEGMENT DB 100 DUP(?) ENDS SEGMENT ASSUME DS:DATA,SS:STACK,CS:CODE MOV AX,DATA Subprog PROC MOV DS,AX ADD AL, BL MOV AL, 1 OR AL, 30H MOV BL, 2 MOV SUM, AL CALL subprog Mov dl,al mov ah,4cH Mov ah,2 int 21h Int 21h ENDS RET END START sub ENDP
主程序和子程序间的关系:调用子程序的程序称为主调程序或 主程序,被调用的程序称为子程序。 2、程序中使用子程序的好处 子程序作为一个功能性模块,供一个程序甚至多个程序使用: 可以简化源程序结构; 提高程序的可读性与可维护性; 有利于代码复用; 提高程序的设计效率。
5.2 子程序的定义、调用和返回
1、子程序的定义:由子程序定义伪指令PROC和ENDP来完成。其 格式如下:
参数传递的基本方法有:
(1)寄存器法:通过CPU寄存器传递参数。传递数据方便、快 捷,但所能传递的数据长度和个数都有限。
(2)变量法:通过内存单元(组)传递参数。传递数据的长度 和个数可不受限制,程序设计比较灵活。 (3)堆栈法:通过堆栈传递参数。用堆栈保存所要传递的数 据或存储地址,利用堆栈数据存取的特点,是常用的参数传 递方法。
DATA SUM DATA STACK STACK CODE START:
CODE END
SEGMENT 通过堆栈——功能最强/最灵活/最复杂 DB 0 ENDS SEGMENT DB 100 DUP(?) ENDS Spr PROC SEGMENT PUSH BP ASSUME DS:DATA,SS:STACK,CS:CODE MOV BP, SP MOV AX,DATA MOV AX, [BP+6] MOV DS,AX MOV BX, [BP+4] MOV AL, 1 ADD AL, BL MOV BL, 2 OR AL, 30H MOV AH,0 MOV DL,AL MOV BH,0 MOV AH,2 PUSH AX INT 21H PUSH BX MOV SUM, AL CALL SPR POP BP POP BX RET POP AX Spr ENDP MOV AH,4CH INT 21H ENDS START
总结
子程序是提高程序设计效率的良好手段,也为模块化设计提供 了很好的基础。
在子程序设计中 • 要明确地定义出这个子程序的入口参数和出口参数,使调用 者能方便地使用子程序。 • 在子程序中要合理地保存主程序和子程序都用到的寄存器和 存储单元,以使主程序能正确地运行。
总结
注意:前面所介绍的三种传递参数的方法,并不是固定不变的。 即它们是可以综合使用的。要按照实现的需要和具体情况的不 同,可以使用其中一种方式,也可以同时使用几种混合的方式, 有的时候还可能并不需要参数的传递。 总之,调用程序和子程序之间的参数传递,的确十分重要, 参数不宜使用太多。参数选择的适当,可以简化程序设计。 参数确定之后,就是如何进行传递的问题。无论采用哪一 种传递方式,都应该保证正确无误的传递。这是调用程序和子 程序的协调关系。这也是在子程序设计中需要认真解决的问题。
clc again: lodsw adc ax,[bx] stosw inc bx inc bx loop again popf ; pop cx pop di pop si pop bx pop bp ;恢复现场 ret 8 ;返回调用点,并废除4个参数共8字节 add64 endp ;子过程结束 code ends end main
code SEGMENT begin: CALL sub1 CALL sub2 CALL sub3 MOV AH, 4CH INT 21H sub1 PROC 、、 RET ENDP PROC 、、 RET ENDP PROC 、、 RET ENDP
sub1 sub2
sub2
sub3
sub3
源自文库
code