汇编语言——子程序调用

主程序与子程序

汇编语言——子程序调用_第1张图片

调用语句CALL

  • CALL指令分成4种类型

      1. CALL子程序名 ;段内直接调用
      1. CALL far ptr子程序名; 段间直接调用
  • 不是很常用的

      1. CALL r16
        CALL WORD PTR m16;段内间接调用(IP发生改变)
      1. CALL DWORD ptr mem;段间间接调用(存储器)
  • CALL指令需要保存返回地址:

    • 段内调用——在同一代码段内进行, 也称近调用偏移地址IP入栈
      SP←SP- 2, SS:[SP]←IP
    • 段间调用——在不同代码段之间进行,也称远调用
      段地址CS和偏移地址IP和入栈
      SP←SP- 2, SS:[SP]←CS
      SP←SP- 2, SS:[SP]←IP

返回指令RET

子程序返回指令

  • 功能:弹出堆栈中由CALL指令压入的返回地址值,迫使CPU返回到主程序中CALL指令的下一条指令去继续执行,该指令常放在子程序的最后
  • 说明:根据段内和段间、有无参数,具体分成4种情况
    (1) RET ;无参数返回
    (2) RET n ;有参数返回 n参数的作用
    需要弹出CALL指令压入堆栈的返回地址
    (3)段内返回——偏移地址IP出栈
    IP←SS:[SP], SP←SP+2
    (4)段间返回——偏移地址IP和段地址CS出栈
    IP←SS:[SP], SP←SP+2
    CS←SS:[SP], SP←SP+2

子程序的定义

使用过程定义语句:
过程名 PROC

过程名 ENDP

子程序结构

  • 调用指令的执行过程
    1、保护断点
    将调用指令的下一条地址(断点)压入堆栈(CS,IP)
    2、获得子程序的入口地址(label)
    子程序第一条指令地址
    3、执行子程序(程序员完成)
    功能实现,参数的保存和恢复(CS,IP)
    4、恢复断点
    将断点的偏移地址弹出。
  • 子程序(过程)调用应处理好三个问题
    1、保护断点(CS,IP入栈及出栈)
    2、保护现场:子程序中用到寄存器/存储器需要保护
    3参数传递:
    寄存器传递:速度快,参数少(寄存器就在CUP内部)
    存储器传输(可存放的数据多)
    堆栈传递

用寄存器传递参数

例:用子程序计算数组元素累加和
入口参数:CX=元素个数,BX=元素的偏移地址 DS:BX=数组的段地址:偏移地址
出口参数:AL=累加和

  • 把参数存于约定的寄存器中,可以传值,也可以传址。
    子程序对带有出口参数的寄存器不能保护和恢复(主程序视具体情况进行保护)
    子程序对带有入口参数的寄存器可以保护,也可以不保护;但最好一致
  • 使用寄存器传递参数时
    带有入口参数的寄存器可以保护,也可以不保护;
    带有出口参数的寄存器则一定不可保护和恢复;
    其他与出口参数无关、而子程序中使用 的寄存器,子程序开始处应该保护,子程序结束、返回主程序之前应该恢复。

用变量传递参数

主程序和子程序直接采用同一个变量名共享同一个变量,实现参数的传递.不同模块间共享时,需要声明

Data segment
COUNT   EQU 5
ARRAY   DB 12H,25H,0F0H,0A3H,03
RESULT  DB ?
Data ends

Code segment
    assume cs:code, ds: data
 start:mov ax,data
     mov ds,ax
     CALL CHECK
Code ends
End start

CHECK PROC
 ……
      LEA BX,ARRAY
……
CHECK ENDP

用堆栈传递参数

主程序将子程序的入口参数压入堆栈,子程序从堆栈中取出参数
子程序将出口参数压入堆栈,主程序弹出堆栈取得它们
多用于数组操作

例子

  • 存储器传递参数
    将一个字节BCD码(十进制数)转换成二进制数
    ;使用寄存器:CX
    ;入口参数: AL存放两位BCD
    ;出口参数: AL存放二进制数
    ;调用其它子程序:无
BCD2BIN PROC FAR
	PUSH CX
	MOV CH,AL
	AND CH,0FH
	MOV CL,4 
	SHR AL,CL
	MOV CL,10
	MUL CL
	ADD AL,CH
	POP CX
	RET
BCD2BIN ENDP

数据段定义两个字型数组,编程序实现数组分别求和(不计溢出),要求用子程序实现求和。
解:

DATA SEGMENT
ARY1 DW 100 DUP(?) ; 定义数组1
SUM1 DW ?;和
ARY2 DW 100 DUP(?) ;定义数组2
SUM2 DW ?;和
DATA ENDS

CODE	SEGMENT 
     ASSUME   CS:CODE,DS:DATA 
START: MOV AX, DATA 
       MOV DS, AX
       LEA  SI, ARY1           ;数组1首地址,入口参数 
       MOV  CX, (SUM1-ARY1)/2  ;数组1加操作次数,入口参数(数组1的长度即length ARY1。/2因为DW)
       CALL SUB_SUM            ;调用求和子程序 
       MOV  SUM1,AX            ;数组1之和送SUM1 
       LEA  SI, ARY2           ;数组2首地址,入口参数 
       MOV  CX, (SUM2-ARY2)/2  ;数组2加操作次数,入口参数 
       CALL SUB_SUM 	       ;调用求和子程序 
       MOV  SUM2,AX            ;数组2之和送SUM2 
       MOV  AH, 4CH 
       INT  21H 
;子程序名 SUB_SUM
;功能:完成一个数组中元素的相加
;入口参数:数组首地址SI,数组元素相加的次数CX
;出口参数:相加结果存在AX中
;占用寄存器:AX
SUB_SUM  PROC	NEAR           ;子程序 
       XOR   AX, AX            ;AX清0 
   L1: ADD   AX, WORD PTR[SI]  ;加数组元素 
       INC   SI
       INC   SI ;以字为地址,SI要加2
       LOOP  L1 ;cx-1
       RET                     ;子程序返回 
SUB_SUM   ENDP                          	
CODE	  ENDS 
          END   START

你可能感兴趣的:(汇编语言)