【发布时间】:2014-05-22 13:15:09
【问题描述】:
我花了半个晚上的时间来编写这段代码,然后用另一半时间让它工作。在不同论坛上打开了许多关于 MASM、斐波那契、股票、部门的主题标签后,我想得到你的帮助。 看起来它在无限循环中存货,因为它总是显示序列 0, 1,
即使我输入 0,它仍然不会跳转到条件跳转指定的标签。
我认为问题很可能出在 displayFib 程序或 displayNum 中
page 55,80
title Fibonacci [FIB.ASM]
.model small
.stack 100h
.data
msg1 db "Please enter the number of terms in the fibonacci sequence to display:",0DH,0AH,"$" ;message to user
msg2 db "Displaying Fibonacci sequence",0DH,0AH,"$" ; message to user
msg3 db ", ","$" ; formating - coma
num1 dw 0 ;this is a numeric variable
num2 dw 0 ; this is a numeric variable
input dw 0 ; this is a numeric variable
fibPrev1 DW 1 ; word numeric value n-1 value
fibPrev2 DW 0 ; word numeric value n-2 value
fib DW 0 ; word numeric value
temp DW 0 ; word numeric value
saveCount DW 0 ;counter storage
.code
extrn clrscr:proc
main proc
mov ax,@data ; set up data segment
mov ds,ax
call clrscr ; clear the screen
mov ah,9 ; send message with instructions for user
mov dx,offset msg1
int 21h
call keyin ;gets user input
SUB AL, 48 ;changes ASCII value into numeric value for further processing
mov num1 , AX ;saves user input to variable num1
call keyin ;gets user input
SUB AL, 48 ;changes ASCII value into numeric value for further processing
mov num2 , AX ;saves user input to variable num2, so now we have both digits
;multiplying num1 10 times
MOV CX, 10
repeat1: ; loop 10 times
MOV AX, NUM1 ;copies value of num1 to AX
ADD input, AX ;adds value from AX
DEC CX ;decrements the counter
JNZ repeat1 ;loops until counter = 0
MOV AX, num2 ;adding the value from num2 so if user entered 83, so it was num1=8 num2=3, then we multiplied 8x10=80, so we add 80+3 and we get 83
ADD input, AX
call newLine
mov ah,9 ; send informative message to user regarding displaying the sequence
mov dx,offset msg2
int 21h
call newLine
call displayFib
call newLine
mov ax,4C00h ; return to DOS
int 21h
main endp
newLine proc ;procedure displays new line
mov dx,0Dh ;line feed
mov ah,2
int 21h
mov dx,0Ah ;carriage return
mov ah,2
int 21h
ret
newLine endp
keyin proc
mov ah, 1 ; getting a key from the keyboard
int 21h
ret
keyin endp
displayFib proc
;display zero as a 0'th term
MOV DX, 30h ; move value 30 hexadecimal to DX, which represents 0
call display
MOV AX, input
CMP AX, 0 ;if the input is 0 in hexadecimal ASCII value then jump to finish
JE finish_it
mov ah,9 ; formating - coma
mov dx,offset msg3
int 21h
;display the 1st term
MOV DX, 31h ; move value 31 hexadecimal to DX, which represents 1
call display
CMP input, 1 ;if the input is 1 in hexadecimal ASCII value then jump to finish
JE finish_it
MOV CX, input ;intializing counter, knowing that first 2 terms were displayed already
SUB CX, 2
repeat:
mov ah,9 ; formating - coma
mov dx,offset msg3
int 21h
MOV AX, fibPrev2 ; calculating the n'th term of a sequence n = (n-1) + (n-2)
ADD AX, fibPrev1
MOV fib, AX
MOV DX, fib
MOV saveCount, CX ;saving the state of the counter as it will be modified in the displayNum
call displayNum
;display the n'th term (current term)
MOV CX, saveCount ;restoring state of the counter
MOV AX, fibPrev1 ; n-1 in the next round of a loop will be n-2
MOV fibPrev2, AX
MOV AX, fib ;n'th term in the next round will be n-1
MOV fibPrev1, AX
DEC CX ;decrementing counter
CMP CX, 1
JL repeat ; loop until counter = 0
finish_it:
ret
displayFib endp
displayNum proc ;display numbers including these with more than one digit
MOV AX, fib ;copying fib to temp
MOV temp, AX
MOV CX,0 ;initializing counter to 0
loop1:
;dividng fib by 10 and pushing reminder on the stock
INC CX ;incrementing counter
MOV ax, temp
MOV bx, 10
SUB dx, dx ;set dx to zero
DIV bx ;BX will contain integer division result and DX remainder
PUSH DX
MOV temp, BX ;temp will hold value of itself integer devided by 10
JNZ loop1
loop2:
POP DX
ADD DX, 30h
call display
JNZ loop2 ;loop until all digits on stack are popped and counter =0
ret
displayNum endp
display proc ; display of a single character
mov ah, 6
int 21h
ret
display endp
end main
【问题讨论】:
-
学习使用调试器。我可以轻松发现的第一个错误是
keyin在AL中返回值,但您随后使用AX。大概AH在那个时候仍然包含1,弄乱了你的号码。 -
感谢您的留言@Jester。根据我们的教授的说法,我们应该使用 AH 来获取用户输入。我试图将 AH 移动到 AX,但它给我的错误是它们不匹配(因为一个是 8 位,另一个是 16 位)。您能建议解决方案吗?
-
一种可能的解决方案是在
keyin中的MOV AH, 0就在RET之前。 -
谢谢小丑!但是在尝试之后它给了我运行时错误 NTVDM CPU 遇到了非法指令 CS:055f IP:02d6 OP:f0 06 9b 06 6e 这让我完全迷失了。选择“关闭”以终止应用程序
标签: assembly masm fibonacci x86-16