Assembly 英特尔8086-输入数字后程序锁定
我对汇编语言非常陌生,我正在做一项作业,要求你输入一个数字,要么输入一个零,要么输入九个数字,将它们存储在堆栈中,然后在输入完数字后将数字相加,并将总和打印到屏幕上。当我组装并链接程序及其外部文件时,它不会出现任何错误;但是,当我运行代码时,它会打印一个空行(没有其他内容),让我输入一个数字,锁定并关闭DOSBox。我一直在试图找出问题所在以及如何解决,但我完全被卡住了。任何帮助都将不胜感激,谢谢Assembly 英特尔8086-输入数字后程序锁定,assembly,x86-16,dosbox,8086,Assembly,X86 16,Dosbox,8086,我对汇编语言非常陌生,我正在做一项作业,要求你输入一个数字,要么输入一个零,要么输入九个数字,将它们存储在堆栈中,然后在输入完数字后将数字相加,并将总和打印到屏幕上。当我组装并链接程序及其外部文件时,它不会出现任何错误;但是,当我运行代码时,它会打印一个空行(没有其他内容),让我输入一个数字,锁定并关闭DOSBox。我一直在试图找出问题所在以及如何解决,但我完全被卡住了。任何帮助都将不胜感激,谢谢 .model small .stack 100h .data count db 0
.model small
.stack 100h
.data
count db 0
sum dw 0
prompt db 0ah, 0dh, 'Enter Value ', '$'
colon db ': ','$'
reply db 0ah, 0dh, 'Sum Equals: ', '$'
.code
extrn indec: proc
extrn outdec: proc
include myMacros.asm
mov ax,@data
mov ds,ax
mov cx,0
mov bx,0
push cx
;jmp L1
L1:
inc count
prtStr prompt
mov cl,count
writeCh count
prtStr colon
call indec
cmp ax,0
je S
push ax
cmp cx,9
jl L1
S:
pop dx
add bx,dx
cmp dx,0
jne S
;prtStr reply
mov ax,bx
call outdec
exit
endp
end
因为您没有显示这些宏,我们只能推测它们是如何运行的。但是,看到您在程序中很早(太早)就将
BX
和CX
寄存器(其余代码所依赖的)归零,我猜这些调用和宏调用中的一个或多个可能会改变这些寄存器
但有一个错误是显而易见的。如果宏writeCh确实写入Ch字符,则应在count变量中存储合适的ASCII码。现在您有了数字[1,9],您希望字符[“1”,“9”]对应于ASCII码[49,57]
.data
count db '0' ; This is a character '0' with ASCII code 48
...
.code
...
push 0 ; Sentinel (*)
L1:
prtStr prompt
inc count
writeCh count
prtStr colon
call indec ; -> AX
test ax, ax
jz S
push ax
cmp count, '9' ; Loose the dependency on the CX register
jb L1 ; Treat ASCII code as UNsigned numbers
S:
xor ax, ax ; Setup close to the consumer and as late as you can. This will
S_: ; improve readability and probably avoid errors too...
pop dx
add ax, dx
test dx, dx ; Got to sentinel ?
jnz S_ ; Not yet
push ax ; In case 'prtStr' clobbers AX
prtStr Reply
pop ax
call outdec
...
(*)如果您在标题中对的引用是严格的,则必须将此push 0
替换为对xor ax,ax
push ax
因为您没有显示这些宏,我们只能推测它们是如何运行的。
但是,看到您在程序中很早(太早)就将BX
和CX
寄存器(其余代码所依赖的)归零,我猜这些调用和宏调用中的一个或多个可能会改变这些寄存器
但有一个错误是显而易见的。如果宏writeCh确实写入Ch字符,则应在count变量中存储合适的ASCII码。现在您有了数字[1,9],您希望字符[“1”,“9”]对应于ASCII码[49,57]
.data
count db '0' ; This is a character '0' with ASCII code 48
...
.code
...
push 0 ; Sentinel (*)
L1:
prtStr prompt
inc count
writeCh count
prtStr colon
call indec ; -> AX
test ax, ax
jz S
push ax
cmp count, '9' ; Loose the dependency on the CX register
jb L1 ; Treat ASCII code as UNsigned numbers
S:
xor ax, ax ; Setup close to the consumer and as late as you can. This will
S_: ; improve readability and probably avoid errors too...
pop dx
add ax, dx
test dx, dx ; Got to sentinel ?
jnz S_ ; Not yet
push ax ; In case 'prtStr' clobbers AX
prtStr Reply
pop ax
call outdec
...
(*)如果您在标题中对的引用是严格的,那么这个push 0
必须替换为一对xor ax,ax
push ax
作为一个开始,您可能应该查看mymacros.asm中的代码。仅根据名称,我猜outdec
不用于显示字符串。更可能的情况是,它接受al中的值,将其转换为字符串并显示。这样做mov al,提示;call outdec
不会按您的意愿进行操作。因此,现在它会打印一个空行,让我输入一个数字,然后它不会让我输入任何其他内容,但它不会关闭DOSBox,并且光标会一直闪烁,因此您所说的更改很有帮助,谢谢!我猜我的问题现在出在L1的某个地方,但我不确定。关于修复什么,您还有其他建议吗?在修复程序时,通常最好按照程序出现的顺序进行修复。有时候你遇到(严重的)问题5是因为(不是很严重的)问题1把事情搞砸了。如果您仍然没有收到提示,您可能应该找到它。如果您计划学习汇编语言(或者任何编程语言),您需要学习如何使用调试器。我不熟悉您正在使用的汇编程序,但我怀疑调试器会向您显示在mov cl,count
处发生的奇怪情况。如果不在数据和cx中保留计数,而只使用cx呢?我建议使用Turbo Debugger 2.01,它可以很好地处理DOSBox中的16位可执行文件:首先,您可能应该看看mymacros.asm中的代码。仅根据名称,我猜outdec
不用于显示字符串。更可能的情况是,它接受al中的值,将其转换为字符串并显示。这样做mov al,提示;call outdec
不会按您的意愿进行操作。因此,现在它会打印一个空行,让我输入一个数字,然后它不会让我输入任何其他内容,但它不会关闭DOSBox,并且光标会一直闪烁,因此您所说的更改很有帮助,谢谢!我猜我的问题现在出在L1的某个地方,但我不确定。关于修复什么,您还有其他建议吗?在修复程序时,通常最好按照程序出现的顺序进行修复。有时候你遇到(严重的)问题5是因为(不是很严重的)问题1把事情搞砸了。如果您仍然没有收到提示,您可能应该找到它。如果您计划学习汇编语言(或者任何编程语言),您需要学习如何使用调试器。我不熟悉您正在使用的汇编程序,但我怀疑调试器会向您显示在mov cl,count
处发生的奇怪情况。如果不在数据和cx中保留计数,而只使用cx呢?我建议使用Turbo Debugger 2.01,它可以很好地处理DOSBox中的16位可执行文件: