【问题标题】:MASM fibonacci sequence based on user input基于用户输入的 MASM 斐波那契数列
【发布时间】: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

【问题讨论】:

  • 学习使用调试器。我可以轻松发现的第一个错误是keyinAL 中返回值,但您随后使用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


【解决方案1】:

SO 不是调试服务,正如我所说,要学会自己使用调试器。 您的代码中存在一些问题:

  1. AHkeyin 之后不为零
  2. 用户的输入必须是 2 位数字(不适用于 1 位数字)
  3. 你的评论说loop until counter = 0你没有这样做。修复:你需要DEC CX; JNZ loop1
  4. BX will contain integer division result - 不正确,结果在 AX 中,无论您使用 BX 作为除数。修复:您需要将MOV temp, BX 调整为MOV temp, AX
  5. JNZ loop1 缺少设置标志的指令,而DIV 没有。修复:插入TEST AX, AX
  6. 您的loop2 缺少循环变量的减量。修复:插入DEC CX

我相信这就是我必须做出的所有改变才能让它发挥作用。

【讨论】:

  • 谢谢小丑。感谢您的建议和帮助。我下载了 cv 调试器,它工作得非常好!我能够找到所有额外的错误,这比以前做的试错和猜谜游戏要好得多。我倾向于忽略调试器,但最终它又回到了我身上。
猜你喜欢
  • 2015-06-05
  • 2018-04-02
  • 1970-01-01
  • 2016-07-14
  • 2022-01-14
  • 2016-01-21
  • 2017-05-15
相关资源
最近更新 更多