在8086程序集中将十六进制转换为十进制ASCII而不使用增量循环

时间:2017-11-24 16:50:03

标签: assembly x86-16

我的问题与我编写的程序有关,该程序获取DX中的值,使用增量循环将其转换为十进制ASCII,并将其存储在字符串变量中。

首先,这是存储在其中的字符串变量:

;This string holds a 16 bit value represented in ascii decimal.
;the first byte is the starting char offset byte. It's used by the 
;procedure that prints it to determine which character to print first.  
;For instance the number "27" would have a starting char offset value of 4.
;This is done to avoid printing unnecessary leading zeros.
;eos is the end of string marker. It has a value of 0.

dec_str   db ?,"00000",eos        

以下是程序:

DX_2_DEC PROC

;CONVERTS A 16 BIT VALUE INTO DECIMAL ASCII CHARACTERS STORING IT
;AS A PRINTABLE STRING IN dec_str.

;EXPECTS THE 16 BIT HEX NUMBER IN DX.
;EXPECTS DS TO BE LOADED WITH DATA SEGMENT textSeg

    push ax
    push cx
    push di


    lea di, dec_str             ;ds:di -> textSeg:dec_str
    inc di                      ;skip past the starting char offset byte
    mov al, '0'                 ;initializing the string with 0's
    mov cx, 5                   ;writing 5 0's
INIT_STR_WITH_ZEROS:            
    mov BYTE PTR [di], al
    inc di
    loop INIT_STR_WITH_ZEROS    ;dec_str is now initialized.


    dec di                      ;dec back to the 5th ascii character

    test dx, 0ffffh             ;if dx = 0, then skip the inc loop
    jz SET_1S_                  ;and hop down to set the starting char
                                ;offset byte to 5

    mov cx, dx                  ;the given 16 bit value is the loop cntr
DECIMAL_ASCII_INC:

    inc BYTE PTR [di-0]         ;inc the 5th ascii char 
    cmp BYTE PTR [di-0], '9'    ;is the 5th character greater than a 9
    jbe INC_DEC_ASCII           ;if not, loop back & inc the 5th ascii char
    mov BYTE PTR [di-0], '0'    ;if so, reset 5th char to 0
    inc BYTE PTR [di-1]         ;and inc the 4th char
    cmp BYTE PTR [di-1], '9'    ;is the 4th character greater than a 9
    jbe INC_DEC_ASCII           ;if not, loop back & inc the 5th ascii char
    mov BYTE PTR [di-0], '0' 
    mov BYTE PTR [di-1], '0'    ;if so reset 5th & 4th char to 0    
    inc BYTE PTR [di-2]         ;and inc the 3rd char
    cmp BYTE PTR [di-2], '9'    ;is the 3rd character greater than a 9
    jbe INC_DEC_ASCII           ;if not, loop back & inc the 5th ascii char
    mov BYTE PTR [di-0], '0' 
    mov BYTE PTR [di-1], '0'
    mov BYTE PTR [di-2], '0'    ;if so reset 5th - 3rd char to 0
    inc BYTE PTR [di-3]         ;and inc the 2nd char
    cmp BYTE PTR [di-3], '9'    ;is the 2nd character greater than a 9
    jbe INC_DEC_ASCII           ;if not, loop back & inc the 5th ascii char
    mov BYTE PTR [di-0], '0'
    mov BYTE PTR [di-1], '0' 
    mov BYTE PTR [di-2], '0'
    mov BYTE PTR [di-3], '0'    ;if so reset 5th - 2nd char to 0
    inc BYTE PTR [di-4]         ;and inc the 1st char
    cmp BYTE PTR [di-4], '7'    ;1st can't be 7 or more (65,535 is the max)
    jb INC_DEC_ASCII            
    pop di
    pop cx
    pop ax
    ret


INC_DEC_ASCII:

    loop DECIMAL_ASCII_INC      ;loop until the ascii decimal characters
                                ;represent the value of the hexadecimal 
                                ;number in dx.                             


    jmp SET_DEC_LEN             ;skip the hop          
SET_1S_:                        ;need a hop since jump is out of range
    jmp SET_1S
SET_DEC_LEN:




    cmp dx, 10000d              
    jb CHK_1000S                ;if dx < 10,000 check the 1000s place value.
    mov BYTE PTR [di-5], 1      ;otherwise, starting char offset byte takes 1
    jmp DONE_WITH_DEC


CHK_1000S:
    cmp dx, 1000d               
    jb CHK_100S                 ;if dx < 1,000 check the 100s place value.
    mov BYTE PTR [di-5], 2      ;otherwise, starting char offset byte takes 2 
    jmp DONE_WITH_DEC


CHK_100S:
    cmp dx, 100d
    jb CHK_10S                  ;if dx < 100 check 10s place value.
    mov BYTE PTR [di-5], 3      ;otherwise, starting char offset byte takes 3
    jmp DONE_WITH_DEC


CHK_10S:
    cmp dx, 10d
    jb SET_1S                   ;if dx < 10 check 1s place value.
    mov BYTE PTR [di-5], 4      ;otherwise, starting char offset byte takes 4
    jmp DONE_WITH_DEC 


SET_1S:                         ;set to 1s place value.
    mov BYTE PTR [di-5], 5      ;starting char offset byte takes 5


DONE_WITH_DEC:



    pop di
    pop cx
    pop ax
    ret

DX_2_DEC ENDP        

此过程有效,它确实将DX转换为十进制ascii字符串,但它并不总是在相同的时间内完成。 DX中的值越大,增量循环执行的时间越长。将十六进制和二进制转换为ascii要容易得多,但每种方法都完全不同。这个程序的姐妹程序DX_2_HEX&amp; DX_2_BIN根本不相似。但是,无论给定16位值的实际大小如何,DX_2_HEX和DX_2_BIN始终执行相同的时间。这就是我想要用这个程序做的。

我有一种感觉我应该使用二进制编码的十进制指令,但在阅读了intel 8086程序员的参考资料之后,我只是看不出它们如何用于将数字从0转换为65,535到十进制ascii。我找不到任何可能导致十进制值大于9,999的转换过程示例。

1 个答案:

答案 0 :(得分:1)

          mov     ax, dx
          lea     di, dec_str
          mov     cl, 5
          mov     bx, 100000
CONVERT:  xor     dx, dx
          div     bx
          add     al, 30h
          mov     si, dx
          mov     [di], al
          inc     di
          mov     ax, bx
          mov     bx, 0Ah
          xor     dx, dx
          div     bx
          mov     bx, ax
          mov     ax, si
          dec     cl
          jnz CONVERT