【问题标题】:Using CALL, RET in assembly x86在汇编 x86 中使用 CALL、RET
【发布时间】:2016-04-12 09:11:09
【问题描述】:

考虑以下使用pushpopcall 的简单汇编代码

CDSEG SEGMENT
MAIN PROC FAR
    ASSUME CS:CDSEG,DS:DTSEG
    MOV AX,DTSEG
    MOV DS,AX

    MOV AX,1010H        ; (1)
    PUSH AX             ; (2)
    CALL FOO            ; (3)
    ADD AX,2            ; (7)
MAIN ENDP   
FOO PROC   
    POP AX              ; (4)
    ADD AX,1            ; (5)
    RET                 ; (6)
FOO ENDP
END MAIN

我的期望是看到

(1) ax = 1010h, stack=????
(2) ax = 1010h, stack=1010h
(3) 
(4) ax = 1010h, stack=????
(5) ax = 1011h
(6)
(7) ax = 1012h

但是,模拟器显示

(1) ax = 1010h, stack=????
(2) ax = 1010h, stack=1010h
(3) 
(4) ax = 000Ch, stack=????
(5) ax = 000Dh
(6) The control never goes back to the main proc
(7) ???

什么问题?

【问题讨论】:

    标签: assembly x86


    【解决方案1】:

    CALL 将返回地址压入堆栈,这就是允许RET 返回该地址的原因。当您在FOOPOP AX 时,您正在从堆栈中弹出返回地址。当您输入FOO 时,您在CALL 之前PUSHed 的值不在堆栈顶部,而是在[SP+2]

    【讨论】:

    • 稍微扩展一下,程序通常不会压栈的值,而是通过栈帧访问它们(使用bp寄存器,需要手动设置) 或没有堆栈帧,直接使用sp。如果您的函数的堆栈上也有局部变量,则堆栈帧很有用。
    • 简单地说:你搞砸了堆栈!因为你弹出了调用的返回地址,所以PROC 返回到无处/某处。
    猜你喜欢
    • 1970-01-01
    • 2015-09-04
    • 2016-11-23
    • 2014-10-04
    • 2013-07-11
    • 2022-12-10
    • 2016-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多