在emu8086中从1打印到<用户输入

时间:2019-04-03 18:49:19

标签: loops assembly emu8086

我想从用户那里得到一个数字(即5),然后从1到<输入(即1 2 3 4)开始打印 但是我的代码不会以“ 4”停止,而是循环运行到“ d”

我知道循环运行CX次 就像在8086中MOVZX不能正常工作一样,这就是为什么我首先将AL移到CL然后将CH清零的原因。

正如有人提到的那样,问题出在我将AL移到CX时,我没有移数值4,而是移34(ASCII值4),所以我的循环运行了34次。

现在如何将用户输入值转换为十进制并将其移动到CX。有什么办法可以将用户输入作为十进制值存储在AL中?

08:00:00

2 个答案:

答案 0 :(得分:3)

MOV AH, 1  ; Get user input 
INT 21H

如果输入 5 ,则AL寄存器将保留数字35h,即该密钥的ASCII码。您显然希望该键代表的是5。您需要减去30h(48)。

mov     ah, 01h  ; DOS.GetKey 
int     21h
sub     al, '0'
dec     al
mov     cl, al
mov     ch, 0

程序的其余部分适合从1到<输入的打印。

答案 1 :(得分:1)

  

现在如何将用户输入值转换为十进制并将其移动到CX。

您陷入了陷阱,使用}while(--cx)以外的指令忘记了loop以外的其他循环条件也是可能的。

loop只是dec cx / jnz的窥孔优化(不影响FLAGS)。仅在实际上是最有效的循环方式时才使用它。 (或者根本不使用它,因为无论如何您都需要理解条件分支,因此省略loop可以使您了解/记住的指令要少得多。此外,on most modern x86 CPUs, loop is much slower than dec/jnz。如果调整为真正的8086,这很好,或优化代码大小以提高速度,但这只是必要的作为优化


编写此循环的最简单,最合乎逻辑的方法是:

    MOV AH, 1     ; read a char from stdin into AL
    INT 21H

    mov   cl, al    ; ending character
    mov   bl, '1'   ; b = current character, starting with '1'

.top:                  ; do {

    ... print CR/LF   (not shown)

    mov   dl, bl
    int   21h            ; With AH=2 from printing CR/LF

    inc   bl             ; b++
    cmp   bl, cl
    jbe  .top          ; }while(b <= end_char);

注意,在打印后 我会增加。如果在打印之前增加计数,则将jb}while(b < end_char)


在实际的loop有效的8086上,它确实在循环中包含更多指令和更多代码字节,因此可能会更慢(如果我们考虑循环开销很重要的情况,而不是3倍慢int 21h在循环内进行系统调用。

但是这与较小的总代码大小(从琐碎的循环设置中)取得了平衡。因此,要在静态代码大小与动态指令计数(以及需要提取的代码字节数,这是8086上的真正问题)之间进行权衡。