...
call mymain
mov ax, 1
...
mymain:
push ax
push ax
ret
这样程序是不能返回原点的。因为子程序使用的堆栈是主程序的,在主程序调用子程序是保存的断点信息被你在子程序中push掉了(sp的值被你修改了),所以无法正确执行。
从中可以看出不足处: 子程序用的是主程序的堆栈段,容易修改主程序的数据。可以在调用子程序时为子程序切换堆栈段使子程序使用自己的堆栈段,在子程序返回时还原主程序的堆栈(当然用相应的算法写个子程序来处理这个问题,可以使子程序自动还原主程序的堆栈。可以讨论一下)例:
mov ax,ss 首先用ax,bx保存ss,sp的值。这样就不担心主程序的堆栈段了
mov bx,sp
(如果在调用子程序中要改变ax和bx的值时,在调用保存这个值,这个就是主程序的堆栈段了,下面例中没有改变值,所以不保存了)
call mymain
mov ax,1
........
mymain:
mov cx,0x7d00(子程序使用新的堆栈段)
mov sp,cx
push cx 改变了子程序的堆栈段,而没改变主程序的堆栈段
push cx
子程序完成后恢复主程序的堆栈段,注意在调用子程序前sp的值以改变,在子程序中要使sp值减2
sub bx,2
mov sp,bx
mov ss,ax 恢复主程序的堆栈段
ret 使用主程序的堆栈段返回主程序
这样做虽然复杂了许多,但子程序使用了自己的堆栈段后不用关心主程序的堆栈是否受到影响。明白了吗?在没用 *** 作系统的介入下(调用什么系统功能呀)在程序消亡前所有的东西都是你自己在控制,这就是汇编。
在这里我想说一下自己的想法,我还没时间去实现(上班苦呀)你可以参考一下(这只是大体想法,有不足处自己修改):
我们可以几个子程序段来实现:
首先可以写个子程序用来切换主程序的堆栈,当然可以在主程序中定义保存相关数据的结构。这里注意这个代码段本身是个子程序调用,在切换段时要注意把返回点从主程序的堆栈段中复制到新段中,同时把主程序的堆栈段的相关信息写到数据结构中去。然后用新的堆栈段就可以返回到主程序中。这样这个切换堆栈子程序就差不多了。
接下来写个还原堆栈子程序段,记住在调用这个子程序段是,我们还在目标子程序中执行代码,所以我们要从数据结构中读取数据还原主程序的堆栈段。
一、堆栈段的定义:是指采用堆栈方式工作的一段内存区域。在采用段式内存管理方式进行程序内存分配的架构中,堆栈段用来存放局部变量和函数返回地址。堆栈段是在程序运行时动态分配使用,只需要通过栈顶指针即可访问。目前大多数CPU中都有专用寄存器可以被用来存放栈顶地址。
二、堆栈段的说明:
1、在程序中,堆栈段主要用于暂时保存一些数据;
2、调用程序如要向子程序传递参数,可在调用之前将参数放在堆栈中,子程序在执行时再将参数从堆栈中取出;
3、.子程序在执行时如要修改寄存器,在执行前应先将寄存器的值压入堆栈,在返回调用程序前,再通过出栈 *** 作恢复这些寄存器的值。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)