经过一些额外的推送后,我来自另一个模块的程序无法 return 正确地转换为来自主模块的主程序

My procedure from another module does not return correctly to main procedure from main module, after some extra pushes

我有2个模块文件,一个主文件和一个辅助文件。在主文件中,我从第二个模块调用一个过程(它从键盘读取一个数字并将其存储在 AX 中)。当我调试代码时,我注意到当代码 returns 从 aux 过程到 main 过程时,它进入无限循环。

main.asm 包含主要过程的模块:

EXTRN READNR:FAR

DATE SEGMENT PARA 'DATA'
     EMPTY DB ?
DATE ENDS

CODEMAIN SEGMENT PARA 'CODE'
ASSUME CS: CODEMAIN, DS: DATE
MAINPROC PROC FAR
    PUSH DS
    XOR AX, AX  
    PUSH AX
    MOV AX, DATE
    MOV DS, AX


    CALL READNR
    
    RET
MAINPROC ENDP
CODEMAIN ENDS
END MAINPROC

aux.asm 带有辅助程序的模块:

DATA SEGMENT PARA 'DATA'
    NUMBER DB 6, ?, 6 DUP(?)
DATA ENDS

AUX SEGMENT PARA 'CODE'
PUBLIC READNR
ASSUME CS: AUX, DS: DATA
READNR PROC FAR
    PUSH AX
    XOR AX, AX
    PUSH DS
    MOV AX, DATA
    MOV DS, AX

    MOV DX, OFFSET NUMBER 
    MOV AH, 0Ah
    INT 21h
    
    MOV BX, 10
    MOV AX, 0
    MOV CX, 0
    MOV SI, 2
    MOV CL, NUMBER[1]
LOOP1:
    MUL BX
    ADD AL, NUMBER[SI]
    SUB AL, 30h
    INC SI
    LOOP LOOP1
    
    RET
READNR ENDP
AUX ENDS
END

我使用这些命令 link 2 个模块:

tasm main
tasm aux
tlink main aux
td main

你能找出它 return 不正确的原因吗?

READNR 推了两次,但没有弹出。我不明白它怎么可能 return 给来电者。

So if I push on the stack in some module and the stack remains non-empty, the program will not return properly to the main module?

是的:call 指令将 return 地址压入堆栈,这就是 ret 指令查找它的地方 — 作为堆栈的顶部项目。如果您通过压入修改堆栈,那么您压入的任何内容现在都位于堆栈的顶部。为了使用 ret 使用 return,函数必须删除所有放置在堆栈上的项目,将堆栈指针恢复到与进入时相同的值。

如果你在堆栈上留下额外的东西,首先 ret 将不会按预期工作,但即使以某种方式可以返回给调用者,调用者也可能会有问题,因为调用者期望堆栈保持他们离开时的状态。