我试图简单地在序列中打印数字,即
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
使用Loop, 首先我将每个数字转换为Hexa打印,然后将其重置为十进制增量1,然后打印下一个直到数字等于9, 当数字等于9时,我使用DAA来简化数字,在旋转和移动数字后,我最终将结果存储在字符串中。
直到16时输出才正常,但在16之后,序列重复,
期望的输出:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
当前输出 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,11,12,13,14,15
为什么会这样呢???
这是我的代码,
MOV CX,20 ;Number of Iterations
MOV DX,1
L1:
PUSH DX
ADD DX,30H
MOV AH,02H ;PRINT Content of DX
INT 21H
POP DX
ADD DX,1
CMP DX,09d ;If number is Greater than 9 jump to L2
JA L2
LOOP L1
L2:
PUSH DX
MOV AX,DX
DAA ;Convert to the Decimal
XOR AH,AH ;SET AH to 0000
ROR AX,1
ROR AX,1
ROR AX,1
ROR AX,1
SHR AH,1
SHR AH,1
SHR AH,1
SHR AH,1
ADC AX,3030h
MOV BX,OFFSET Result
MOV byte ptr[BX],5 ; Length of the String
MOV byte ptr[BX+4],'$' ;5th position of string , $=Terminator
MOV byte ptr[BX+3],AH ;2nd Number onto 4th position
MOV byte ptr[BX+2],AL ;3rd number onto 3rd Position
MOV DX,BX
ADD DX,02 ;1st 2 positions of String are type of string and
length respectively
MOV AH,09H ;to print the string
INT 21H
POP DX
ADD DX,1
LOOP L2
MOV AH,4CH ;Return control to the DOS
INT 21H
P.S:我从这张图表中获得了解数字的帮助。
答案 0 :(得分:4)
8086代码只允许立即为1(或cl)进行移位和旋转计数。要启用286代码,请告诉文件顶部的Tasm“.286”。这是猜测。
我记得以前用来在al:
打印一个两位数字的方式aam
add ax, 3030h
xchg al, ah
int 29h
mov al, ah
int 29h
答案 1 :(得分:3)
试一试,虽然我不确定,但我无法快速测试。
但是我不建议使用两个循环,而是建议在整个数字中使用一个循环。
此外,我感觉问题与DAA
指令有关,我不习惯,因为它在64位模式下不受支持。
无论如何,这就是我要做的事情:
mov cx,20
mov al,1
mov bl,10 ; divisor
mov bp,offset Result ; no need to load this in the loop!!!
L1: mov dx,ax ; save to register, not to stack
cmp ax,09d
ja L2 ; number has two digits
add al,30h ; ASCII addend
; insert your output code here
jmp L3 ; jump over the two digit code
L2: xor ah,ah
div bl ; divides AX by ten (no rotate or shift needed)
; quotient in AL, remainder in AH (correct order for little endian)
add ax,3030h
; insert your output code here (note that the buffer/string address is loaded to BP)
L3: mov ax,dx
inc ax
loop L1
; done
如果您不介意一位数字的前导零,那就更容易了。
div
指令可能比daa
加ror
加shr
更贵,但你的四轮旋转/转换会更糟: - /
(正如我所说,我无法尝试......让你开放......如果它不起作用,只需回复。)
-
[更新:
另一种方法,特别是将div
放在这个简单的数字分离情况下,将增加6到数字大于9(即10d = 0ah - (+ 6) - > 16d = 10h ;这是daa
也可以做的事情,那么你就可以使用之前使用的旋转/移位组合。
更好的是添加246,然后添加到AX
,之后您可以简单地使用ror ax,8
(或rol
- 在这种情况下无关紧要),i。即10d = 0ah - (+ 246) - > 256d = 100h,以及15d = 0fh - (+ 246) - > 261 = 105h。将它分别旋转为0001h或0501h,加3030h,就完成了。
/更新]
[update level =“2”
有趣的是......我实际上打算在第一级更新中编写它,但忘记了它:而不是rol
ling by 8,或者 - 如果你的TASM真的不支持{{1通过立即 - 八次滚动一次,您当然也可以使用rol
指令,它在寄存器之间交换值,在这种情况下
xchg
将完成交换这两个寄存器内容的工作。
还有一条 xchg al,ah
指令用于反转寄存器中的字节顺序,但它显然只适用于32位宽的寄存器。
/更新]
答案 2 :(得分:0)
.model small
.stack 100
.code
mov ax, 0ffffh ; hex number to find it's bcd
mov bx, 0000
mov dh, 0
l9 : cmp ax, 10000 ; if ax>10000
jb l2
sub ax, 10000 ; subtract 10000
inc dh ; add 1 to dh
jmp l9
l2 : cmp ax, 1000 ; if ax>1000
jb l4
sub ax, 1000
add bx, 1000h ; add 1000h to result
jmp l2
l4 : cmp ax, 100 ; if ax>100
jb l6
sub ax, 100
add bx, 100h ; add 100h to result
jmp l4
l6 : cmp ax, 10 ; if ax>10
jb l8
sub ax, 10
add bx, 10h ; add 10h to result
jmp l6
l8 : add bx, ax ; add remainder
; to result
mov ah, 02
mov cx, 0204h ; Count to display
; 2 digits
go: rol dh, cl
mov dl, dh
and dl, 0fh
add dl, 30h ; display 2 msb digits
int 21h
dec ch
jnz go
mov ch, 04h ; Count of digits to be
; displayed
mov cl, 04h ; Count to roll by 4 bits
l12: rol bx, cl ; roll bl so that msb
; comes to lsb
mov dl, bl ; load dl with data to be
; displayed
and dl, 0fH ; get only lsb
cmp dl, 09 ; check if digit is 0-9 or letter A-F
jbe l14
add dl, 07 ; if letter add 37H else only add 30H
l14: add dl, 30H
mov ah, 02 ; Function 2 under INT 21H (Display character)
int 21H
dec ch ; Decrement Count
jnz l12
mov ah, 4cH ; Terminate Program
int 21H
end