程序返回不正确

凯梅内森德雷

我正在使用TASM进行装配8086,我有两个文件。我从一个文件调用读取过程,并想在另一个文件中使用3次。第一次使用程序崩溃后。

read.asm文件:

PUBLIC READ
DATA SEGMENT PARA PUBLIC 'DATA'
BUFFER DB 200 DUP(?)
FLAG DB 0
DATA ENDS

CODE SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CODE, DS:DATA
;PUBLIC READ

; read procedure reads a string character by character from the keyboard 
READ PROC FAR
PUSH DS
    XOR AX,AX
    PUSH AX
    MOV AX,DATA
    MOV DS,AX
    XOR DI,DI

; readloop is the loop for reading the string character by character
READLOOP:
    MOV AH,01H
    INT 21H; al will get the character
    MOV BUFFER[DI],AL; the character is stored
    INC DI
    CMP AL,0DH
    JNZ READLOOP; the reading continues until the ENTER key is pressed

; we display the string
    MOV AL,0
    MOV BUFFER[DI],24H
    LEA DX,BUFFER
    MOV AH,09H
    INT 21H

; converting the string to a real number
    XOR SI,SI
    XOR DX,DX
    MOV DL,BUFFER[SI]
    XOR AX,AX
    XOR CX,CX

; converter loop converts the string to a real number memorizing where the decimal point was
CONVERTER:
    CMP DL,2EH; searching for the decimal point
    JZ FLOATINGPOINT
    CMP FLAG,1
    JNZ NEXT2
    INC CX; position of the decimal point stored

NEXT2:
    SUB DL,30H; deducing the character which digit is
    PUSH DX; storing the value of dx on the stack
    MOV BX,10
    MUL BX
    POP DX
    ADD AX,DX; retrieving the value as an integer in AX
    JMP NEXT

FLOATINGPOINT:
    MOV FLAG,1

NEXT:
    INC SI
    MOV DL,BUFFER[SI]
    CMP DL,0DH; doing the conversion until the ENTER key is pressed
    JNZ CONVERTER
    RET
READ ENDP

SAMPLE PROC FAR
    RET
SAMPLE ENDP
CODE ENDS
    END SAMPLE

main.asm文件:

GLOBAL READ:FAR
DATA SEGMENT PARA PUBLIC 'DATA'
SIDEONE DW ?
SIDETWO DW ?
SIDETHREE DW ?
HALFPERIMETER DB ?
DECIMALPOINTONE DB ?
DECIMALPOINTTWO DB ?
DECIMALPOINTTHREE DB ?
MESSAGE1 DB 10,13,10,13,"Please input the length of the first side:$"
MESSAGE2 DB 10,13,"Please input the length of the second side:$"
MESSAGE3 DB 10,13,"Please input the length of the third side:$"
WELCOMEMESSAGE DB "Welcome to my triangle area calculator!$"
CONTINUEMESSAGE DB 10,13,10,13,"Do you want another try? y-yes n-no:$"
RESULTMESSAGE DB 10,13,10,13,"The area of the triangle is:$"
RESULT DB ?
DATA ENDS

CODE SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CODE, DS:DATA
MAIN PROC FAR
    PUSH DS
    XOR AX,AX
    PUSH AX
    MOV AX,DATA
    MOV DS,AX
    MOV DX,OFFSET WELCOMEMESSAGE
    MOV AH,09H
    INT 21H
    XOR DX,DX
    XOR AX,AX

START:
    LEA DX,MESSAGE1
    MOV AH,09H
    INT 21H
    XOR DX,DX
    CALL READ
    MOV SIDEONE,AX
    MOV DECIMALPOINTONE,CL
    XOR DX,DX
    XOR AX,AX
    LEA DX,MESSAGE2
    MOV AH,09H
    INT 21H
    XOR DX,DX
    CALL READ
    MOV SIDETWO,AX
    MOV DECIMALPOINTTWO,CL
    XOR DX,DX
    XOR AX,AX
    LEA DX,MESSAGE3
    MOV AH,09H
    INT 21H
    XOR DX,DX
    CALL READ
    MOV SIDETHREE,AX
    MOV DECIMALPOINTTHREE,CL
    XOR DX,DX
    XOR AX,AX
    LEA DX,RESULTMESSAGE
    MOV AH,09H
    INT 21H
    XOR DX,DX
    ;MOV DX,RESULT
    ;MOV AH,09H
    ;INT 21H
    ;XOR DX,DX
    XOR AX,AX
    MOV DX,OFFSET CONTINUEMESSAGE
    MOV AH,09H
    INT 21H
    MOV AH,01H
    INT 21H
    CMP AL,79H
    JZ START
    CMP AL,6EH
    JZ FINISHPROGRAM

FINISHPROGRAM:
    MOV AH,4CH
    INT 21H
    RET
MAIN ENDP
CODE ENDS
END MAIN
mcleod_ideafix

这是您砸碎的堆栈。就在您的READ程序开始时

PUSH DS
XOR AX,AX
PUSH AX

EXE程序的开头需要此序列以完成一条RET FAR指令(终止EXE文件的一种老方法),但该程序调用的任何过程均不需要此序列删除它。

另外,只要DS在程序的任何位置都没有更新,就只需要在程序开始时使用序列MOV AX,DATA/MOV DS,AX一次,而不是在每个过程中都需要。

如果您以这种方式终止程序,则可以有效地避免上述顺序:

MOV AX,4C00h
INT 21h

这是终止DOS进程的正确方法。旧的方式是通过使用INT 20h,但INT 20h需要CS以指向PSP该程序,因此的PUSH DS / XOR AX,AX / PUSH AX序列:一个RET FAR指令将加载CS:IP与值DS:0000h继续在的开始时执行PSP,其中INT 20h指令被置于DOS装载器(一个老记忆什么曾经是中终止程序CALL 0RST 0序列CP/M

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章