转换十六进制/十进制数字(Assely TASM)



我正试图简单地按顺序打印数字,即

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,18,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:我从这张图表中得到了帮助,理解了这些数字。

http://www.cheat-sheets.org/saved-copy/ascii.png

8086代码只允许移位和旋转计数的立即数为1(或cl)。要启用286代码,请在文件顶部告诉Tasm".286"。这只是猜测。

我记得我曾经用al打印两位数的数字:

aam
add ax, 3030h
xchg al, ah
int 29h
mov al, ah
int 29h

只是尝试一下,尽管我不确定,而且我不能快速测试它。

但是,与其使用两个循环,我建议对整组数字使用一个循环。

此外,我觉得这个问题与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指令可能比daarorshr更贵,但您的四进制旋转/移位会更糟:-/

(正如我所说,我不能尝试……把这个留给你……如果它不起作用,请回问。)

[更新:

另一种方法,尤其是在这种琐碎的数字分离情况下,为了避免div,将6加到大于9的数字上(即10d=0ah-(+6)-->16d=10h;这也是daa的作用),然后您可以使用以前使用的旋转/移位组合。

更好的方法是添加246,然后添加到AX,之后您可以简单地使用ror ax,8(或rol—在这种情况下无关紧要),即10d=0ah-(+246)-->256d=100h,以及15d=0ah-(+446)-->261=105h。分别旋转到0001h或0501h,加3030h,就完成了。

/更新]

[更新级别="2">

多么有趣。。。实际上,我本打算在一级更新中编写它,但不知何故忘记了:而不是rol乘以8,或者—如果您的TASM真的不支持rolling,请立即—八次一次滚动,当然也可以使用xchg指令,它在寄存器之间交换值,在这种情况下是

xchg al,ah

将完成交换这两个寄存器的内容的工作。

还有一个bswap指令用于反转寄存器中的字节顺序,但它显然只适用于宽度超过32位的寄存器。

/更新]

.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

最新更新