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

Assembly 程序已将控制权返回到程序集8086中的操作系统,assembly,x86,x86-16,emu8086,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 第一条指令是push bp,因此堆栈顶部的

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

程序已将控制权返回到操作系统

当它到达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

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

然后再做一些事情,包括操纵
sp
(指向堆栈顶部的指针),但就在
ret
之前,它指向旧的
bp

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

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

要修复,请在
ret
之前添加
pop bp
(通过
mov sp、bp
还原
sp
值后)

无论何时,无论是通过
push/pop
add/sub sp
显式操作堆栈,还是通过
call/ret
隐式操作堆栈,在进一步使用堆栈之前,确保在每个代码路径中以正确的
sp
值结束。也就是说,通常每个
push
都需要它的配对
pop
和每个
调用ld通过
ret
返回,除非您有足够的经验打破这些规则并通过不同的方法将堆栈调整到正确的状态


顺便说一句,在你的入口点的堆栈中是否真的有返回地址是值得怀疑的(你的问题不清楚,如果你有其他代码调用这个,或者它是你程序的入口点)


如果这类似于DOS可执行文件,并且它是入口点,那么您应该使用OS服务调用来结束您的程序。

您使用的是哪种汇编程序?而且,这个问题没有意义。当您运行程序时,汇编程序会做些什么?当您运行问题时,汇编程序不会执行。尝试执行时,您是否看到此消息汇编您的代码,或者在尝试运行二进制文件时?您确定这实际上是一个错误吗?您的问题是什么?调用twoMash后的代码是什么?您没有发布它,但它可能会结束程序(例如
mov ax,4c00h
int 21h
)。可能这就是你的程序结束的原因,因为没有更多的代码。你创建了COM程序还是EXE?COM程序中应该有
org 100h
。我想知道你是否创建了一个COM程序,twoMash函数先被执行,到达RET,然后返回操作系统而没有到达
main
。这是很难说,除非我们看到了你的完整代码。