从 1 打印到 < emu8086 中的用户输入
Print from 1 to < user input in emu8086
我想从用户那里得到一个数字(即5)然后从1开始打印到<输入(即1 2 3 4)
但是我的代码不会在“4”处停止,而是循环运行到 "d"
我知道循环运行 CX 次
和 8086 一样,MOVZX 不起作用,这就是为什么一开始我将 AL 移到 CL,然后将 CH 归零。
正如有人提到的,问题是当我将 AL 移动到 CX 时,我没有移动值 4,而是移动了 34(ASCII 值 4),所以我的循环运行了 34 次。
现在如何将我的用户输入值转换为十进制并将其移至 CX。有什么方法可以将用户输入作为十进制值存储在 AL 中吗?
org 100h
MOV AH, 1 ; Get user input
INT 21H
DEC AL ; Dec AL to satisfy the condition that it will print till < input
MOV BL,31H ; Initialize BL so that the output starts printing from 1
MOV CL,Al ; set counter register CX
MOV CH,00
Print:
MOV AH, 2 ; for output printing
MOV DL,0DH ; for output printing
INT 21H ; for output printing
MOV DL,0AH ; for output printing
INT 21H ; for output printing
MOV AH,2
MOV DL,BL ; print what is in BL
INT 21H
INC BL ; then increment BL
LOOP Print ; supposed to run the loop on Print what is the value in CL times
hlt
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 开始打印到 < 输入。
Now how do I convert my user input value to decimal and move that to CX.
你已经陷入了忘记 }while(--cx)
以外的循环条件是可能的陷阱,使用 loop
.[=23 以外的指令=]
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)
.
在真正的 8086 上,loop
是高效的,这在循环内确实有更多的指令和更多的代码字节,因此可能会更慢(如果我们考虑循环开销很重要的情况,而不是循环内的 3 倍慢 int 21h
系统调用)。
但这与较小的总代码大小(来自简单的循环设置)进行了权衡。因此,这是静态代码大小与动态指令数(以及需要获取的代码字节数,这是 8086 上的真正问题)之间的权衡。
我想从用户那里得到一个数字(即5)然后从1开始打印到<输入(即1 2 3 4) 但是我的代码不会在“4”处停止,而是循环运行到 "d"
我知道循环运行 CX 次 和 8086 一样,MOVZX 不起作用,这就是为什么一开始我将 AL 移到 CL,然后将 CH 归零。
正如有人提到的,问题是当我将 AL 移动到 CX 时,我没有移动值 4,而是移动了 34(ASCII 值 4),所以我的循环运行了 34 次。
现在如何将我的用户输入值转换为十进制并将其移至 CX。有什么方法可以将用户输入作为十进制值存储在 AL 中吗?
org 100h
MOV AH, 1 ; Get user input
INT 21H
DEC AL ; Dec AL to satisfy the condition that it will print till < input
MOV BL,31H ; Initialize BL so that the output starts printing from 1
MOV CL,Al ; set counter register CX
MOV CH,00
Print:
MOV AH, 2 ; for output printing
MOV DL,0DH ; for output printing
INT 21H ; for output printing
MOV DL,0AH ; for output printing
INT 21H ; for output printing
MOV AH,2
MOV DL,BL ; print what is in BL
INT 21H
INC BL ; then increment BL
LOOP Print ; supposed to run the loop on Print what is the value in CL times
hlt
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 开始打印到 < 输入。
Now how do I convert my user input value to decimal and move that to CX.
你已经陷入了忘记 }while(--cx)
以外的循环条件是可能的陷阱,使用 loop
.[=23 以外的指令=]
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)
.
在真正的 8086 上,loop
是高效的,这在循环内确实有更多的指令和更多的代码字节,因此可能会更慢(如果我们考虑循环开销很重要的情况,而不是循环内的 3 倍慢 int 21h
系统调用)。
但这与较小的总代码大小(来自简单的循环设置)进行了权衡。因此,这是静态代码大小与动态指令数(以及需要获取的代码字节数,这是 8086 上的真正问题)之间的权衡。