所以我写了一个uni赋值 - 一个减去两个输入小数的程序(最多10个字符ea)。第一次迭代按预期工作。但是,当我重新启动程序时,由于某种原因会记住第二个操作数。 输入它的提示确实出现了,但是然后被跳过,好像我已经输入了一些东西 - 事实上我进入第一次迭代时也是如此。 问题是:为什么会发生,我该如何解决?第一个提示正常工作。
提示符在INPUT_2下:
.model small
.386
stack 100h
dataseg
inputMsg1 db 0Ah, 0Dh, 'Enter first operand', 0Ah, 0Dh, '$'
inputMsg2 db 0Ah, 0Dh, 'Enter second operand', 0Ah, 0Dh, '$'
inputMax1 db 11
inputLen1 db ?
input1 db 12 dup(?)
input1Packd db 5 dup(0)
inputMax2 db 11
inputLen2 db ?
input2 db 12 dup(?)
input2Packd db 5 dup(0)
packMode db 0 ;Режим упаковки: 1 - первая цифра, 2 - вторая
resMsg db 0Ah, 0Dh, 'Result: $'
res db 9 dup(' '),'$'
retryMsg db 0Ah, 0Dh
db 'Press Any Key to continue, ESC to quit'
db '$'
errorMsg db 0Ah, 0Dh, 'Something went wrong. Try again$'
codeseg
START:
startupcode
jmp INPUT_1
INPUT_1_ERROR:
lea DX, errorMsg
mov AH, 09h
int 21h
INPUT_1:
lea DX, inputMsg1
mov AH, 09h
int 21h
lea DX, inputMax1
mov AH, 0Ah
int 21h
cmp inputLen1, 0
jz INPUT_1_ERROR
INPUT_1_PROCESS:
lea BX, input1
lea DX, input1Packd
xor CX, CX
mov CL, inputLen1
mov SI, CX
dec SI
mov DI, 4
INPUT_1_LOOP:
mov AL, [BX][SI]
cmp AL, '0'
jb INPUT_1_ERROR
cmp AL, '9'
ja INPUT_1_ERROR
and AL, 0Fh
mov AH, packMode
cmp AH, 0
jnz INPUT_1_PACK_SECOND
INPUT_1_PACK_FIRST:
inc AH
push BX
mov BX, DX
mov [BX][DI], AL
pop BX
jmp INPUT_1_PACK_FINISHED
INPUT_1_PACK_SECOND:
dec AH
shl AL, 4
push BX
mov BX, DX
or [BX][DI], AL
pop BX
dec DI
INPUT_1_PACK_FINISHED:
mov packMode, AH
dec SI
loop INPUT_1_LOOP
mov packMode, 0
jmp INPUT_2
INPUT_2_ERROR:
lea DX, errorMsg
mov AH, 09h
int 21h
INPUT_2:
lea DX, inputMsg2
mov AH, 09h
int 21h
lea DX, inputMax2
mov AH, 0Ah
int 21h
cmp inputLen2, 0
jz INPUT_2_ERROR
INPUT_2_PROCESS:
lea BX, input2
lea DX, input2Packd
xor CX, CX
mov CL, inputLen2
mov SI, CX
dec SI
mov DI, 4
INPUT_2_LOOP:
mov AL, [BX][SI]
cmp AL, '0'
jb INPUT_2_ERROR
cmp AL, '9'
ja INPUT_2_ERROR
and AL, 0Fh
mov AH, packMode
cmp AH, 0
jnz INPUT_2_PACK_SECOND
INPUT_2_PACK_FIRST:
inc AH
push BX
mov BX, DX
mov [BX][DI], AL
pop BX
jmp INPUT_2_PACK_FINISHED
INPUT_2_PACK_SECOND:
dec AH
shl AL, 4
push BX
mov BX, DX
or [BX][DI], AL
pop BX
dec DI
INPUT_2_PACK_FINISHED:
mov packMode, AH
dec SI
loop INPUT_2_LOOP
MATH_SETUP:
mov SI, 4
mov CX, 4
mov DI, 7
MATH:
lea BX, input1Packd
mov AL, [BX][SI]
lea BX, input2Packd
mov AH, [BX][SI]
sbb AL, AH
pushf
das
dec SI
mov AH, AL
lea BX, res
and AL, 0Fh
or AL, 30h
mov [BX][DI], AL
dec DI
shr AH, 4
or AH, 30h
mov [BX][DI], AH
dec DI
popf
loop MATH
lea BX, res
mov CX, 7
mov SI, 0
SHORTEN:
mov AL, [BX][SI]
cmp AL, '0'
jnz WRAPUP
inc SI
loop SHORTEN
WRAPUP:
push CX
lea DX, resMsg
mov AH, 09h
int 21h
lea DX, res
pop CX
cmp CX, 0
jz SKIP_SHORTEN
PRINT_SHORTEN:
add DX, 7
sub DX, CX
jmp FINISH_SHORTEN
SKIP_SHORTEN:
add DX, 6
FINISH_SHORTEN:
mov AH, 09h
int 21h
lea DX, retryMsg
mov AH, 09h
int 21h
mov AH, 01h
int 21h
cmp AL, 1Bh
jz QUIT
lea BX, input1Packd
mov DX, 1
BCD_CLEANUP:
mov DI, 0
mov CX, 5
BCD_CLEANUP_LOOP:
mov [BX][DI], 0
inc DI
loop BCD_CLEANUP_LOOP
lea BX, input2Packd
cmp DX, 1
mov DX, 0
jz BCD_CLEANUP
jmp START
QUIT:
exitcode 0
end START
任何更好的代码建议也会受到欢迎,但如果您对此问题没有答案,则不需要。
答案 0 :(得分:1)
DOS缓冲输入功能0Ah允许您在所提供的输入缓冲区的存储空间中具有预设文本。有关此DOS函数的完整说明,请参阅how buffered input works。
您的程序第一次运行 inputLen1 和 inputLen2 字段为空时,因为您使用db ?
在源中定义它们的方式转换为零。
但是当你重新运行代码时,情况就不再如此了!长度仍显示您在上一次运行中获得的内容。在相同的输入缓冲区上再次调用函数0Ah之前,需要将这两个字段归零。
mov DX, 0
jz BCD_CLEANUP
mov inputLen1, DL ;DL=0
mov inputLen2, DL ;DL=0
jmp START
MATH 循环在CF
方面存在一些问题。
sbb al, ah
指令取决于进位标志中的值,但是忽略确保它在此循环的第一次迭代时关闭。只需添加clc
:
clc
MATH:
lea BX, input1Packd
mov AL, [BX][SI]
lea BX, input2Packd
mov AH, [BX][SI]
sbb AL, AH
das
指令使用从sbb
指令获得的进位标志,但它是您需要保留的das
指令的进位标志/ restore让它通过循环传播。
sbb AL, AH
das
pushf
...减去两个输入小数的程序(最多 10 个字符ea)......
如果您输入9或10个字符,那么这些最高有效数字将不会被考虑在内,因为 MATH_SETUP 确实将您限制为8个字符(这反过来又是一个很好的事情,因为 res 缓冲区只有空间显示8个字符)!
MATH_SETUP:
mov SI, 4 <-- Could permit 10 packed BCD digits
mov CX, 4 <-- Max 8 characters
mov DI, 7 <-- Max 8 characters