我正在使用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
这是您砸碎的堆栈。就在您的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 0
或RST 0
序列CP/M
)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句