Tasm - 装配循环

Tasm - Assembly Loop

我想在用户输入正确的密码后显示"Hello World",但如果密码不正确,程序将提示是(Y)/否(N),如果用户输入是(Y ),程序会给用户 3 次显示 "Hello World" 的机会,如果用户输入 No(N),程序将退出。 我的问题是,每次我 select Yes(Y),程序一直循环,如果我输入 No(N),它就会结束,

这是我的代码(我跳过了一些部分)

   ...
    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

我不知道这些代码是否正确,我现在没有我的代码副本,而且,如果我的代码和对问题的解释看起来很愚蠢,我很抱歉,但如果有人能帮忙吗,那太好了,如果你能给我你的另一个想法就更好了:)

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

很可能这个 unconditional jmp 是为了成为 conditional jne.


pool:
dec cx
jz full

您不需要在循环顶部使用 dec cxjz full。下面的 loop pool 指令已经完成了所需的工作。 (被 Sami Kuhmonen 观察到)。

然而...
因为 the loop instruction is slow (Observed by 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 寄存器中的 return 代码。写起来真是不费吹灰之力:

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