调用子程序的指令是 CALL(实际上是ACALL或LCALL)。CALL指令用于将程序的控制权从当前位置转移到子程序的入口地址,执行子程序,并在子程序执行完毕后返回到调用它的位置继续执行后续代码。
调用子程序的基本格式和操作
段内直接调用
```assembly
CALL DST
```
其中,`DST`是子程序入口地址的16位偏移量。执行此指令时,当前指令之后的地址(即返回地址)会被压入堆栈,然后程序会跳转到`DST`所指示的地址执行子程序。
段内间接调用
```assembly
CALL [EA]
```
其中,`EA`是一个寄存器或存储单元,包含子程序入口地址。执行此指令时,当前指令之后的地址会被压入堆栈,然后程序会跳转到`EA`所指示的地址执行子程序。
调用子程序后的返回
子程序执行完毕后,会使用 RET指令返回到调用它的主程序。RET指令会从堆栈中弹出先前压入的返回地址,从而恢复主程序的执行。
示例
```assembly
; 主程序
main:
MOV R3, 7
CALL ALL_THE_ZEROS; 调用子程序
MOV R7, 4
CALL ALL_THE_ZEROS; 再次调用子程序
RET ; 返回主程序
; 子程序
ALL_THE_ZEROS:
MOV R0, 0
MOV R1, 1
MOV R2, 2
MOV R3, 3
MOV R4, 4
MOV R5, 5
MOV R6, 6
MOV R7, 7
RET ; 返回主程序
```
在这个示例中,`main`程序调用`ALL_THE_ZEROS`子程序两次,每次调用后都会使用RET指令返回到主程序继续执行。