由于是段内调用,所以,CALL指令只把返回地址的偏移量(即IP的内容)压栈,如图7.6(a)所示。在进入子程序后,为了能读取传递过来的参数,需要用BP来访问堆栈,所以要先保护BP原来的值,再把当前SP的值传送给BP。
于是,当前BP所指向的堆栈单元与最后一个参数Paran之间隔着BP的原值和返回地址的偏移量,也就是说:二者之间相差4个字节。具体情况如图7.6(b)所示。
(b)、子程序寄存器保护后的堆栈情况
在子程序中读取用堆栈传递参数的一般方法如下程序片段所示。
SUBPRO PROC?NEAR PUSH BP ;保护寄存器BP MOV BP, SP ;用寄存器BP来访问堆栈,读取参数 … ;保护其它寄存器的指令 MOV Paran, [BP+4] ;保护其它寄存器的指令 … MOV Para1, [BP+4+2*(n-1)] … SUBPRO ENDP
在段间调用子程序时,CALL指令会把返回地址的偏移量和段寄存器CS的内容都压栈,如图7.7(a)所示。在进入子程序后,与前面“段内调用子程序”一样,也需要用BP来读取传递过来的参数,所以,也要先保护BP原来的值,再把当前SP的值传送给BP。
这时,当前BP所指向的堆栈单元与最后一个参数Paran之间隔着BP的原值、返回地址的偏移量和段地址,所以,二者之间相差6个字节。具体情况如图7.7(b)所示。
(b)、子程序寄存器保护后的堆栈情况
在段间调用时,除了多一个返回段地址外,其它的内容与“段内调用”的情况完全一致,所以,在读取第i个参数时,只要用[BP+6+4*(n-i)]代替[BP+4+2(n-i)]即可(假设每个参数都是字类型)。