111111
精灵王
精灵王
  • 注册日期2010-12-08
  • 发帖数640
  • QQ
  • 火币1103枚
  • 粉丝120
  • 关注75
  • 社区明星
阅读:2516回复:0

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

楼主#
更多 发布于:2013-01-25 17:59

堆栈是一个特殊的数据结构,它通常是用来保存程序的返回地址。当用它来传递参数时,势必会造成数据和返回地址混合在一起的局面,用起来要特别仔细。
具体做法如下:
(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)]即可(假设每个参数都是字类型)。

喜欢0 评分0
游客

返回顶部