My question pertains to a procedure that I wrote which takes the value in DX, converts it to decimal ASCII using an increment loop, and stores it in a string variable.
First, here is the string variable it is stored in:
;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
And here is the procedure:
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
This procedure works, it does convert DX into a decimal ascii string, but it doesn't always do it in the same amount of time. The greater the value in DX the longer the increment loop takes to execute. Converting hexadecimal, and binary to ascii is far easier, but each method is radically different. This procedure's sister procedures DX_2_HEX & DX_2_BIN do not resemble each other at all. However, DX_2_HEX and DX_2_BIN always take the same amount of time to execute, regardless of the actual size of the given 16 bit value. That's what i'm looking to do with this procedure.
I have a feeling I should be using binary coded decimal instructions, but after reading the intel 8086 programmer's reference I just don't see how they would be useful for converting a number from 0 through to 65,535 into decimal ascii. I can't find any example of a conversion process that can result in a decimal value greater than 9,999.