我是这个汇编语言(emu8086)的新手,我只是想问一下这段代码是否有问题。我想显示平均成绩,但输出只有“平均”一词,并且不显示任何数字。
我应该做什么来解决或调试我的代码?
.MODEL SMALL
.DATA
VAL1 DB ?
DISPLAY1 DB 0AH,0DH,'NUMBER OF SUBJECTS :','$'
DISPLAY2 DB 0AH,0DH,'ENTER GRADE:','$'
DISPLAY3 DB 0AH,0DH,'AVEARGE:','$'
BUFFER DB 3,4 DUP(?)
.CODE
MAIN PROC
.STARTUP
LEA DX,DISPLAY1
MOV AH,09H
INT 21H
MOV AH,01H
INT 21H
SUB AL,30H
MOV CL,AL
MOV BL,AL
MOV AL,00
MOV VAL1,AL
LBL1:
LEA DX,DISPLAY2
MOV AH,09H
INT 21H
MOV AH,0AH
LEA DX,BUFFER
INT 21H
SUB AL,30H
ADD AL,VAL1
MOV VAL1,AL
LOOP LBL1
LBL2:
LEA DX,DISPLAY3
MOV AH,09H
INT 21H
MOV AX,00
MOV AL,VAL1
DIV BL
ADD AX,3030H
MOV DX,AX
MOV AH,02H
INT 21H
MOV AH,4CH
INT 21H
.EXIT
MAIN ENDP
END MAIN
MOV AH,0AH LEA DX,BUFFER INT 21H SUB AL,30H
第一个错误是您正在使用 DOS.BufferedInput 函数 0Ah 输入成绩,但没有从缓冲区中检索数字。您似乎期望在 AL 寄存器中找到它,就像 DOS.GetCharacter 函数 01h 的情况一样。
LOOP LBL1
第二个错误是您使用的
loop
指令取决于整个 CX 寄存器,但您的代码仅设置 CX 的 CL 部分。当你的程序启动时,你不应该依赖任何寄存器内容,当然,除非这些设置有很好的记录。
ADD AX,3030H MOV DX,AX MOV AH,02H INT 21H
第三个错误是,您似乎期望显示由两位数字组成的“平均成绩”,并通过单次调用 DOS.PrintCharacter 函数 02h 来完成。
对于这个简单的练习,我们可以假设和他们的成绩都是个位数。当然,平均成绩也将是个位数。 使用 DOS.Getcharacter 函数 01h 就可以了,并且您正在使用从字符到数字表示的值的正确转换。但是,在处理用户输入时,您永远无法真正信任用户向您的程序提供有效的输入。由您来验证输入。对于一位数来说,这很简单:
GetDigit0_9:
mov ah, 01h ; DOS.GetCharacter
int 21h ; -> AL
sub al, '0'
cmp al, 9
ja GetDigit0_9
注意无意识的“无限循环”和“被零除”问题。如果用户为
科目数
输入 0,则不能允许运行等级循环或执行
div bl
指令。使用 jcxz
(JumpOnCXZero) 指令
LBL0:
call GetDigit0_9 ; -> AX=[0,9]
mov cx, ax
jcxz LBL0 ; Guard against 0 number of subjects
jcxz LBL3 ; Guard against 0 number of subjects
LBL1:
...
loop LBL1
LBL2:
...
LBL3:
mov ax, 4C00h ; DOS.Terminate
int 21h
...
LEA DX, DISPLAY1
MOV AH, 09h ; DOS.PrintString
INT 21h
call GetDigit0_9 ; -> AX=[0,9]
mov cx, ax
mov bl, al ; (*)
MOV VAL1, 0
jcxz LBL3 ; Guard against 0 number of subjects
LBL1:
LEA DX, DISPLAY2
MOV AH, 09h ; DOS.PrintString
INT 21h
call GetDigit0_9 ; -> AX=[0,9]
add VAL1, al
loop LBL1
LBL2:
LEA DX, DISPLAY3
MOV AH, 09h ; DOS.PrintString
INT 21h
mov ah, 0
mov al, VAL1
div bl ; (*)
add al, '0'
mov dl, al
mov ah, 02h ; DOS.PrintCharacter
int 21h
LBL3:
mov ax, 4C00h ; DOS.Terminate
int 21h
; IN () OUT (ax)
GetDigit0_9:
mov ah, 01h ; DOS.GetCharacter
int 21h ; -> AL
sub al, '0'
cmp al, 9
ja GetDigit0_9
mov ah, 0
ret
...