程序已将控制权返回到程序集8086中的操作系统

时间:2017-01-04 19:00:39

标签: assembly x86 x86-16 emu8086

当我运行我的程序时,汇编程序说:

  

程序已恢复对操作系统的控制

到达 RET 指令时。代码如下:

twoMash PROC
    push bp
    mov bp, sp
    sub sp, 2

    NOT ax
    ADD ax,1

    mov sp,bp
    ret
twoMash ENDP

main以这种方式定义:

main:
    mov ax,100b
    push ax
    call twoMash

1 个答案:

答案 0 :(得分:2)

第一条指令是push bp,因此堆栈顶部的值现在是bp的值。

然后你做了更多的事情,包括操纵sp(指向堆栈顶部的指针),但在ret之前它指向旧的bp值。

ret将从堆栈中弹出值,并将ip(指令指针)设置为该值。在正常情况下,它应该在堆栈顶部具有要执行的下一条指令的地址(通常由call指令放置,执行ret的反作用,推送下一条指令的地址堆栈上有call,然后将ip设置为call指令中的参数值。

但是在你的代码中,ip被设置为旧的bp值,这很可能指向某处堆栈内存(或“更糟糕”),因此CPU将接下来尝试执行数据字节代码,行为是意外的(返回操作系统实际上是非常好的最终结果,这种错误通常以应用程序崩溃或数据丢失而告终。)

要解决此问题,请在pop bp之前添加ret(将sp值恢复为mov sp,bp后)。

每当您通过push/popadd/sub sp显式操作堆栈,或者call/ret隐式操作堆栈时,请确保在使用之前在每个代码路径中以正确的sp值结束进一步堆叠。 IE浏览器。通常每个push需要配对pop,每个call应该由ret返回,除非您有足够的经验打破这些规则并通过不同方式调整堆栈以纠正状态。

顺便说一句,这是值得怀疑的,是否在您的入口点处的堆栈中确实存在 的返回地址(如果您有其他代码call,那么您的问题就不清楚了这个,或者它是你的程序的入口点。)

如果这是DOS可执行文件,并且它是入口点,那么您应该使用int 21h, 4Ch OS服务调用结束您的程序。