2017-08-27 116 views
2

一旦用户输入了正确的密码,我想显示“Hello World”,但是如果密码不正确,程序会提示输入Yes(Y)/ No(N),如果用户输入Yes Y),程序将给用户三次机会显示“Hello World”,如果用户输入了No(N),程序将退出。 我的问题是,每次我选择是(Y),该程序保持循环,其刚刚结束,如果我进入否(N),Tasm - Assembly Loop

这里是我的代码(我已经跳过某些部分)

... 
    org 0100h 
    .code 

    mov ah, @data 
    mov ds, ah 


    mov cx, 3 

    pool: 
    dec cx 
    jz full ;jump if equal to zero seems of no effect, the loop is still counting 

    dsply: 
    <codes here are for requesting and comparing the password> 

    ... 
    ... 
    ... 
    cmp bl, al 
    jne errr 
    cmp cl, al 
    jmp welc 

    errr: 
    mov ah, 9 
    lea dx, pmpt ; Displays whether the Yes(Y)/No(N) 
    int 21h 
    mov ah, 1 
    mov cl, al 
    int 21h 

    cmp cl, 'Y' 
    je dsply 
    cmp cl, 'N' 
    je endmain 

    loop pool 

    full: 
    mov ah, 9 
    lea dx, att ;att will display You've Exceeded 
    int 21h 
    jmp endmain 

    welc: 
    mov ah, 9 
    lea dx, hw ; Displaying Hello World 
    int 21h 
    jmp endmain 

    endmain: 
    mov ah, 4ch 
    int 21h 
    end main 

我不知道这段代码是否正确,我现在没有我的代码的副本,而且,如果我的代码和问题的解释看起来很愚蠢,我很抱歉,但如果有人可以请帮助,这将是伟大的,更伟大的,如果你能给我你的另一种想法:)

+2

你不应该发布代码,甚至可能不是实际的代码。但只要想想你在代码中对CX寄存器做了什么,那就应该告诉你为什么它不会为零。也不应该有理由使用'loop',然后手动'dec cx'。 –

+0

您是否尝试过使用调试器单步调试? –

+0

@SamiKuhmonen我的错误,对不起,但仍然,谢谢你!您的建议非常感谢 – user8141558

回答

2
errr: 
    mov ah, 9 
    lea dx, pmpt ; Displays whether the Yes(Y)/No(N) 
    int 21h 
    mov ah, 1 
    mov cl, al 
    int 21h 

根本没有在CL寄存器中输入!
您需要将mov cl, al指令移动到int 21h指令之下。


mov ah, @data 
mov ds, ah 

我不明白这是如何工作的。你应该在这里使用一个16位寄存器。

mov ax, @data 
mov ds, ax 

cmp cl, al 
jmp welc 

最大的可能是这无条件jmp是为了成为条件jne


pool: 
dec cx 
jz full 

你不需要这个dec cxjz full在你的循环顶部。下面的loop pool指令已经完成了所需的工作。 (由Sami Kuhmonen观察)。

但是...
因为the loop instruction is slow(由Peter Cordes观察),你应该避免使用它,类似于您在上环上方的冗余指令代码替换它。
但是等等,还有一件事情是错误的!您的循环使用CX寄存器作为其迭代计数器,但同时循环体内的代码使用此相同的CX寄存器用于其他目的。这不可避免地会导致问题!你需要注意你如何使用这些寄存器。

这是一个解决方案:

mov  cx, 3 
pool: 
    push cx  ;(1) Save the iteration counter on the stack 
dsply: 
    ... 
    <codes here are for requesting and comparing the password> 
    ... 
    pop  cx  ;(1) Restore the iteration counter 
    dec  cx 
    jnz  pool 
full: 
    mov  ah, 9 

cmp cl, 'Y' 
je dsply 
cmp cl, 'N' 
je endmain 

一旦你得到了你的程序的工作,你会在这里有一个潜在的问题。当用户键入一个小的“y”或一个小的“n”时会发生什么?
程序不会识别它!

这将是最好的资本输入:

and cl, 11011111b 
cmp cl, 'Y' 
je dsply 
cmp cl, 'N' 
je endmain 

请使用DOS API,因为它打算使用。函数TerminateWithReturnCode函数确实会在AL寄存器中返回代码。这是一个真正的小型努力,写:

mov ax, 4C00h ;Function number in AH, Return code in AL 
int 21h 
+0

请不要建议人们开始使用'loop'。 [它在现代CPU上很慢](https://stackoverflow.com/questions/35742570/why-is-the-loop-instruction-slow-couldnt-intel-have-implemented-it-efficiently),这可能更好学习使用条件分支进行循环的更一般的方法。我已经看到了太多的16位代码,只是盲目地使用'loop'时,如果使用别的东西作为循环条件并且不绑定'cx',会更方便。很明显,初学者陷入了思考'循环'是循环的唯一途径。 –

+0

嗨,九月,感谢您在我的代码中的建议,它真的很感激您已经告诉它有什么问题,xD,我会与您的话保持联系,虽然我还没有编辑和测试过您的修订版本,但您看起来太好了,谢谢你这么多!:) – user8141558

+0

@PeterCordes感谢您对'loop'指令的建议。我用学分编辑了我的答案。我应该在下次对不起,因为我习惯于使用这个指令... –