Assembly 装配循环错误

Assembly 装配循环错误,assembly,masm,Assembly,Masm,我正在尝试在汇编(masm)中编写一个程序,该程序将接受用户输入,并且该程序将输出一个从0到该输入的计数(介于0到99之间)。我遇到的错误是,无论我输入什么数字,程序都会循环到看似随机的数字,然后终止。任何帮助都将不胜感激 cseg segment 'code' assume cs:cseg, ds:cseg, ss:cseg, es:cseg org 100h start: mov ah, 09 mov dx, offset Intro int 21

我正在尝试在汇编(masm)中编写一个程序,该程序将接受用户输入,并且该程序将输出一个从0到该输入的计数(介于0到99之间)。我遇到的错误是,无论我输入什么数字,程序都会循环到看似随机的数字,然后终止。任何帮助都将不胜感激

cseg segment 'code'
assume cs:cseg, ds:cseg, ss:cseg, es:cseg

    org 100h

    start:
    mov ah, 09
    mov dx, offset Intro
    int 21h

    mov ah, 01
    int 21h
    sub al, 30h

    mov bl,0Ah
    mul bl
    mov bl, al

    mov ah, 01
    int 21h
    sub al, 30h

    add bl, al
    mov cl, bl
    jmp again

    again:
    mov ah, 09
    mov dx, offset Hello
    int 21h
    mov dx, offset msg1
    int 21h
    mov dx, offset msg
    int 21h
    inc byte ptr msg
    mov al, msg

    cmp al, 3ah
    jg reset
    loopne again
reset:mov byte ptr msg, 30h
    inc byte ptr msg1
    cmp cx, 0
    jg again
    jmp done

    done:
    mov ah, 4ch
    int 21h

    org 200h
    Intro db "Please input how many times you would like the loop to run." , 20h, 20h, "$"
    Hello db "hello world" , 20h, 20h, "$"
    msg db 30h, 13, 10, "$"
    msg1 db 30h, "$"
    cseg ends
    end start
两个问题:

  • 您将
    bl
    分配给
    cl
    ,而不清除
    ch
    部分,最好使用类似
    movzx-cx,bl

  • 您没有更改cx,在比较之前,在
    cmp cx,0之前添加
    dec cx


  • 建议:无需再次使用
    jmp
    jmp done
    指令
    loopne
    使用
    CX
    寄存器,只需初始化
    CL
    寄存器,该寄存器是
    CX
    的低位字节。如果坚持使用
    loopne
    ,请清除
    CH
    ,这是
    CX
    的高位字节

    当然,解决方案要简单得多。
    保持修改文本计数器的逻辑与主循环的逻辑无关。最糟糕的情况是,文本计数器将毫无意义地增加一次。
    CX
    中移动用户输入的值也没有好处。您也可以从
    BL
    使用它,甚至可以更好地使用它

     add  bl, al              ;BL has user input 00..99
    again:
     mov  ah, 09
     mov  dx, offset Hello
     int  21h
     mov  dx, offset msg1
     int  21h
     mov  dx, offset msg
     int  21h
    
          ; This is the textual counter update
     inc  byte ptr msg        ;Raise the ones
     mov  al, msg
     cmp  al, "9"
     jbe  SameDecade
     mov  byte ptr msg, "0"   ;Reset the ones
     inc  byte ptr msg1       ;Raise the tens
    SameDecade:
    
          ; This is the main loop counter update
     sub  bl, 1
     jnb  again
    
     mov  ax, 4C00h           ;DOS.TerminateWithExitcode
     int  21h
    

    dec-cx
    已经设置了标志(就像从
    cmp-cx,1
    递减之前一样,如果您想具体说明它如何为
    jg
    设置标志)
    decx/jnz
    是一个有用的习惯用法。(当然,它没有设置CF,所以它与
    cmp
    不太一样)@PeterCordes对,我只是按照最初的代码明确测试cx,我建议你可以说“用
    dec cx
    /
    jnz
    替换
    cmp cx,0
    /
    jg
    ”。但事实上,我不确定这是否适合这个项目。我没有遵循全部逻辑;可能他们打算在
    reset
    情况下不接触循环计数器,并有效地重试主循环的相同迭代。(如果没有跳转到
    reset
    ,则使用
    loopne
    )如果只使用
    jge
    /
    loop
    ,而不是让
    loopne
    也检查标志并在
    ==0x3a
    的情况下失败,则更有意义。