子程序的调用通常伴随着主程序和子程序之间的参数传递。主程序要把一些参数传递给子程序,子程序的运行结果也要传回给主程序,在主程序和子程序之间进行参数传递的方法通常有三种:利用寄存器传递、利用存储区传递和利用堆栈传递。
1.通过寄存器传递参数
这是一种快速和简便的参数传递方法,主程序将参数直接放置在预先约定好的寄存器中传递给子程序,子程序的运行结果也可以通过这种方式返回给主程序。由于寄存器的数量和容量有限,通过寄存器传递的一般都是简单参数,参数的类型通常为简单的字节、字或双字,数量则不能超过可用的寄存器数量。下面程序段就是一个通过寄存器传递参数的例子。
在这个例子里,COMDIV子程序用来实现计算两个无符号数的最大公约数,子程序的输入参数是两个无符号数,输出参数是这两个无符号数的最大公约数(也是一个无符号数)。作为输入参数的两个无符号数通过AX和BX寄存器由主程序传递给子程序,最后,计算的结果通过AX寄存器返回给主程序。
2.通过存储区传递参数
通过寄存器传递参数简单而且快速,但是通过寄存器传递的参数在数量和种类上受到很大的限制,无法传递大量和复杂的参数,这时通过存储区进行参数传递就成为一种可行的选择。在设计程序时,将参数定义在一块连续的存储单元中,主程序依照预先定义的规则将需要传递的参数存放在一段连续的存储区里,再将存储区的首地址通过其他方式(比如前面介绍的通过寄存器传递)传递给子程序。子程序通过对这一段存储区的数据进行处理,就可以得到主程序传来的参数了。同样的,子程序也可以通过这种方式将处理结果返回给主程序。下面就是一个通过存储区传递参数的例子。(www.xing528.com)
3.通过堆栈传递参数
除了通过寄存器和存储区进行参数传递之外,子程序的调用过程中还可以通过堆栈实现参数的传递。在CALL和RET指令被执行时,处理机的当前指令指针将被存入或弹出堆栈,栈顶指针的地址将随着子程序的调用和返回不断变化,通过堆栈进行参数传递可以比较容易地应对复杂的子程序调用,尤其是子程序递归调用的情况。但是,通过堆栈传递参数通常用于主程序向子程序传递参数,由于堆栈后入先出的特性,子程序的返回值无法通过堆栈返回给主程序。由于通过堆栈传递参数适应范围广泛,参数类型和数量不受限制,所以被广泛采用在子程序的设计之中。大部分高级语言的编译器输出代码都采用这种方式来向子程序传递参数,而返回值的传递通常采用通过寄存器传递参数的方式。
由于堆栈不仅仅用来传递参数,还被用来记录子程序的返回地址,保存处理机现场信息等,所以在通过堆栈向子程序传递参数的时候一定要注意栈顶指针的正确维护,避免因为参数和子程序的返回地址混淆造成子程序无法正确返回。栈顶指针SP通常用来维护当前堆栈栈顶位置的信息,子程序引用参数的时候,通常使用另一个基址指针BP来引用主程序传来的参数。下面的程序段就是一个通过堆栈传递参数的例子。
上面的FIBNACCI子程序实现了计算Fibnacci数列的功能,参数通过压入堆栈的一个字传递,在子程序中使用[BP+4]来引用参数。设计使用堆栈传递参数的子程序时需要注意两点:①子程序中需要使用到的寄存器最好通过PUSH指令压入堆栈以保护寄存器的值,在从子程序返回之前再用POP指令将寄存器的值恢复。②从子程序返回时需要对栈顶指针进行调整,以清除压入堆栈的参数,这种调整可以通过RET n指令完成,也可以在返回主程序后由主程序通过ADD SP,n指令完成。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。