assembly – 转换十六进制/十进制数字(Assemly-TASM)

我试图简单地在序列中打印数字,即

1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20

使用循环,
首先我将每个数字转换为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:我从这张图表中获得了解数字的帮助.

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

最佳答案
试一试,虽然我不确定,但我无法快速测试.

但是我没有使用两个循环,而是建议在整个数字中使用一个循环.

此外,我感觉问题与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,就完成了.

/更新]

[更新级别=“2”

多么有趣…我实际上打算在第一级更新中写它,但是忘了它:不是滚动8,或者 – 如果你的TASM真的不支持立即滚动 – 八次滚动一次,你在这种情况下,当然也可以使用xchg指令,它在寄存器之间交换值

  xchg al,ah

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

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

/更新]

转载注明原文:assembly – 转换十六进制/十进制数字(Assemly-TASM) - 代码日志