我想从用户那里得到一个数字(即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
答案 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上的真正问题)之间进行权衡。