经典汇编语言教程:7.3.3 堆栈传递参数

7.3.3 堆栈传递参数

堆栈是一个特殊的数据结构,它通常是用来保存程序的返回地址。当用它来传递参数时,势必会造成数据和返回地址混合在一起的局面,用起来要特别仔细。

具体做法如下:

(1)、当用堆栈传递入口参数时,要在调用子程序前把有关参数依次压栈,子程序从堆栈中取到入口参数;

(2)、当用堆栈传递出口参数时,要在子程序返回前,把有关参数依次压栈(这里还需要做点额外操作,要保证返回地址一定在栈顶),调用程序就可以从堆栈中取到出口参数。

在通常情况下,我们用堆栈传入口参数,用寄存器传出口参数。

1、用堆栈传递入口参数的调用方法:

PUSHPara1
PUSHParan;把n个字的参数压栈
CALLSUBPRO;调用子程序SUBPRO

2、在子程序中取入口参数的方法:

、段内调用子程序

由于是段内调用,所以,CALL指令只把返回地址的偏移量(即IP的内容)压栈,如图7.6(a)所示。在进入子程序后,为了能读取传递过来的参数,需要用BP来访问堆栈,所以要先保护BP原来的值,再把当前SP的值传送给BP。

于是,当前BP所指向的堆栈单元与最后一个参数Paran之间隔着BP的原值和返回地址的偏移量,也就是说:二者之间相差4个字节。具体情况如图7.6(b)所示。

(a)、进入子程序时堆栈情况(b)、子程序寄存器保护后的堆栈情况
图7.6 在段内调用情况下子程序所能访问的堆栈情况

在子程序中读取用堆栈传递参数的一般方法如下程序片段所示。

SUBPROPROC  NEAR
PUSHBP;保护寄存器BP
MOVBP, SP;用寄存器BP来访问堆栈,读取参数
;保护其它寄存器的指令
MOVParan, [BP+4];保护其它寄存器的指令
MOVPara1, [BP+4+2*(n-1)]
SUBPROENDP

、段间调用子程序

在段间调用子程序时,CALL指令会把返回地址的偏移量和段寄存器CS的内容都压栈,如图7.7(a)所示。在进入子程序后,与前面“段内调用子程序”一样,也需要用BP来读取传递过来的参数,所以,也要先保护BP原来的值,再把当前SP的值传送给BP。

这时,当前BP所指向的堆栈单元与最后一个参数Paran之间隔着BP的原值、返回地址的偏移量和段地址,所以,二者之间相差6个字节。具体情况如图7.7(b)所示。

(a)、进入子程序时堆栈情况(b)、子程序寄存器保护后的堆栈情况
图7.7 在段间调用情况下子程序所能访问的堆栈情况

在段间调用时,除了多一个返回段地址外,其它的内容与“段内调用”的情况完全一致,所以,在读取第i个参数时,只要用[BP+6+4*(n-i)]代替[BP+4+2(n-i)]即可(假设每个参数都是字类型)。

上页:上一课 下页:下一课

经典汇编语言教程·相关目录

第1章 汇编语言的由来,数据类型第2章 CPU资源和存储器
第3章 操作数的寻址方式第4章 标识符和表达式
第5章 微机CPU的指令系统第6章 程序的基本结构
第7章 子程序和库第8章 输入输出和中断
第9章 宏第10章 应用程序设计
第11章 数值运算协处理器第12章 汇编语言和C语言
汇编语言重要附录Windows API函数大全
版权所有 © 中山市飞娥软件工作室 证书:粤ICP备09170368号