flat assembler
Message board for the users of flat assembler.

Index > DOS > efficient register value to ascii conversion routine

Author
Thread Post new topic Reply to topic
sina



Joined: 18 Aug 2003
Posts: 132
Location: istanbul turkey
sina 04 Dec 2018, 10:53
Hi all,

I am looking for a routine to convert the value stored in ax (0x1234) using 16 bit registers
and print out that value using int21h dos interrupt
so the output from this asm block would be "1234" in dos command prompt.

any examples?
Post 04 Dec 2018, 10:53
View user's profile Send private message ICQ Number Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8392
Location: Kraków, Poland
Tomasz Grysztar 04 Dec 2018, 14:01
This is actually a quite useful basic example that perhaps should be publicly available in annotated version as a learning material. And it only took me a couple of minutes to write it, so it is not a big deal to give it to a public domain as an educational sample for anyone that wants (or needs) to learn some basics of 16-bit assembly programming in DOS:
Code:
org 100h                        ; DOS .COM program, loaded at address 100h in a segment pointed to by CS, DS, ES and SS

start:

        mov     ax,0x1234
        call    print_hex_16

        int     20h             ; exit program

print_hex_16:
; in: ax = 16-bit number
        mov     dx,ax           ; keep a copy of the number
        mov     bx,hex_table    ; DS:BX now points to the table of ASCII characters representing the digits
        mov     di,txt_digits   ; ES:DI now points to place in memory where the converted number shall be stored
        mov     cx,4            ; number of digits
    .convert_digit:
        mov     al,dh           ; take the highest nibble
        shr     al,4            ;  (nibble is a 4-bit portion, it corresponds to single hexadecimal digit)
        shl     dx,4            ; shift the remaining nibbles one up
        xlatb                   ; convert number in AL according to the table at DS:BX
        stosb                   ; store digit at ES:DI, increase DI
        loop    .convert_digit  ; decrease CX, if still not zero, jump back and repeat the loop
        mov     ah,9            ; DOS function 9, to print the prepared text
        mov     dx,txt_prefix   ; DS:DX should point to the complete text to print, ended with '$' character
        int     21h             ; call DOS
        ret

hex_table db '0123456789ABCDEF'

txt_prefix db '0x'              ; beginning of the produced string
txt_digits db '0000'            ; reserve digits, immediately after prefix
txt_suffix db '$'               ; special character recognized by DOS as the end of the string to print    
Post 04 Dec 2018, 14:01
View user's profile Send private message Visit poster's website Reply with quote
sina



Joined: 18 Aug 2003
Posts: 132
Location: istanbul turkey
sina 05 Dec 2018, 07:12
well, you ask for something and god answers Smile

below is what I could come up with, and yes your's is better, thx.
Love&Hate Tomasz Smile

Code:
mov ax, 01234h
call print_word
int 020h ; exit to dos interrupt

print_word:
push ax; put the value of ax on top of stack
shr ax, 8 ; right shift value of ax 8 bits (get leftmost two nibbles)
call print_byte
pop ax; restore value of ax
push ax; put the value of ax on top of stack
and ax, 0ffh ; get last 8 bits of ax (get rightmost two nibbles)
call print_byte
pop ax; restore value of ax
ret ; return

print_byte:
push ax; put the value of ax on top of stack
shr al, 4 ; right shift value of al 4 bits(get left nibble)
call printchar
pop ax; restore value of ax
and al, 0fh ; get last 4 bits of al(get right nibble)
call printchar
ret ; return

printchar:
add al, 030h ; add hex value 30 to convert to ascii(0=30h, 9=39h)
cmp al, 039h ; compare value with ascii code for 9
jle printchar_letter; jump if value is less than or equal(ZF, CF)
add al, 07h ; add 7 to convert numbers bigger than 9 to ascii(A=41h)

printchar_letter:
mov dl, al; move character to write to dl
mov ah, 02h ; set int21h mode to write character to stdout
int 021h ; execute interrupt
ret ; return
    
Post 05 Dec 2018, 07:12
View user's profile Send private message ICQ Number Reply with quote
TightCoderEx



Joined: 14 Feb 2013
Posts: 58
Location: Alberta
TightCoderEx 05 Dec 2018, 09:56
Here is another example and you'll probably find there be as many combinations and permutations as there are programmers. I use this quite often, especially for volatile data when once it's done with and because it's on the stack, it disappears.

Building output from the end provides an easy way of padding output.

Code:
        org     0x100

        push    bp
        mov     bp, sp          ; Create a procedure frame

        mov     cx, 4
        std                     ; So index register get automatically decremented
        mov     di, sp
        dec     di
        sub     sp, 16          ; Give ourselves lots of room
        mov     al, '$'
        stosb                   ; Set terminating character
        mov     ax, 0x3d0f

    ; Even if AX = 0, this will print at least one '0'

Conv:   push    ax
        and     ax, 15          ; Strip all but lower 4 bits
        cmp     al, 9
        jbe     @F

        add     al, 7           ; So AL will be (A-Z)

  @@:   add     al, '0'
        stosb
        dec     cl
        pop     ax
        shr     ax, 4
        jnz     Conv            ; When AX = 0, no point doing anymore conversions

        or      cl, cl          ; CX > 0 means with want to padd buffer
        jz      @F
        mov     al, ' '         ; AL can be whatever you want to padd leading spaces with
        rep     stosb

   @@:  cld                     ; Set auto-increment again
        mov     dx, di
        inc     dx              ; Bump ahead to actual first character
        mov     ah, 9
        int     0x21

        leave                   ; Restore SP to return to executive
        ret    

This is not a competition, but as a matter of curiosity, this code comes in @
58 bytes
sina's 54
Tomasz's 62
Post 05 Dec 2018, 09:56
View user's profile Send private message Visit poster's website Reply with quote
sina



Joined: 18 Aug 2003
Posts: 132
Location: istanbul turkey
sina 05 Dec 2018, 10:11
thanks for the effort
well to be honest, I love the hex table and xlatb approach
Post 05 Dec 2018, 10:11
View user's profile Send private message ICQ Number Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8392
Location: Kraków, Poland
Tomasz Grysztar 05 Dec 2018, 10:24
Well, if you aimed for reduced size, you could cut out the table (including the BX setup) and replace XLATB with this tricky sequence:
Code:
        cmp     al,10           ; if x < 10, set CF = 1
        sbb     al,69h          ; 0-9: 96h .. 9Fh, A-F: A1h..A6h
        das                     ; 0-9: subtr. 66h -> 30h-39h,
                                ; A-F: subtr. 60h -> 41h..46h    
(This is so-called Allison’s algorithm.)
Post 05 Dec 2018, 10:24
View user's profile Send private message Visit poster's website Reply with quote
Mikl___



Joined: 30 Dec 2014
Posts: 143
Location: Russian Federation, Irkutsk
Mikl___ 05 Dec 2018, 11:00
  1. Code:
    ...
    Hex2:add al,90h ;if in al was the number 0..9, then in al
    ; will be 90h..99h, if in al there was a digit 0Ah..0Fh,
    ; then in al will be 9Ah..9Fh
    daa ; 0-9: 90h..99h CF=0
    ; A-F: 00h..05h CF=1
    adc al,40h ; 0-9: D0h..D9h
    ; A-F: 41h..46h
    daa ; 0-9: 30h..39h
    ; A-F: 41h..46h
    stosb; put the value from AL into the string    
  2. Code:
    and al,0Fh; reset the older tetrad
    cmp al,10; if al < 10, CF = 1
    sbb ah,ah; if al < 10, then ah=0, else ah=0FFh
    and ah,1; reset CF and AF, in ah will 0 or 1
    daa; if in al was 0..9, then the contents of al will not change
    add al,'1'; if in al was A..F then in al will 10h..15h
    sub al,ah
    stosb; put the value from AL into the string    
  3. Code:
    and eax,0Fh; reset the older tetrad
    cmp al,10; if al < 10, CF = 1
    adc ah,0; if al < 10, then ah=1, else ah=0
    daa; if in al was 0..9, then the contents of al will not change
    add al,'1'; if in al was A..F then in al will 10h..15h
    sub al,ah
    stosb; put the value from AL into the string    


  4. Code:
    and eax,0Fh; reset the older tetrad
    cmp al,10; if al < 10, CF = 1
    sbb ebx,ebx; if al < 10, then ebx=-1, else ebx=0
    and ebx,ebx; reset CF and AF
    daa; if in al was 0..9, then the contents of al will not change
    lea eax,[ebx+eax+31h]; if A..F then will 10h..15h
    stosb; put the value from AL into the string    


  5. Code:
    cmp al,10;if al < 10, CF = 1
    sbb ebx,ebx; if al < 10, then ebx=0, else ebx=-1 CF=AF=1
    daa ; if in al was A..F, then al will 10h..15h
    and ebx,-103; if 0..9, then al will 66h..6Fh
    lea eax,[eax+ebx+31h]; if A..F, then al will 41h..46h
    stosb; put the value from AL into the string    


  6. Code:
    and al,0Fh; reset the older tetrad
    cmp al,10; if al < 10, CF = 1
    sbb ebx,ebx; if СF=0, then ebx=0, else ebx=-1
    and ebx,-13; reset CF and AF, in ebx will 0 or -13
    das; if 0..9, the contents of al will not change
    lea eax,[eax+ebx+3Dh]; if A..F, then al will 3..9
    stosb; put the value from AL into the string    


  7. Code:
    and al,0Fh; reset the older tetrad
    cmp al,10; if al < 10, CF = 1
    sbb ebx,ebx; if СF=0, then ebx=0, else ebx=-1 CF=AF=1
    das; if 0..9, then the contents of al will not change
    and ebx,-167; if A..F, then al will 3..9
    lea eax,[eax+ebx+3Dh]
    stosb; put the value from AL into the string    


  8. Code:
    and al,0Fh; reset the older tetrad
    cmp al,10; if al < 10, CF = 1
    cmc ; if al < 10, CF = 0
    adc al,30h;if в al 0..9, then in al will 30h..39h,
    ; if in al 0Ah..0Fh, then in al will 3Bh..40h
    daa ; 0-9: 30h..39h,
    ; A-F: 3Bh..40h add 6 -> 41h..46h
    stosb; put the value from AL into the string    


  9. Code:
    and al,0Fh; reset the older tetrad
    daa ;F->15h 1->1
    add al,0F0h;F0+15h->05h CF=1 F0+1->F1 CF=0
    adc al,40h ;46h 31h
    stosb; put the value from AL into the string    


  10. Code:
    and al,0Fh; reset the older tetrad
    daa ; F->15h 1->1
    add al,70h; 70h+15h->85h SF=1 70h+1->71h SF=0
    cbw ; ah=0FFh ah=0
    sub al,ah ; 85+1->86h 71h
    sub al,40h; 46h 31h
    stosb; put the value from AL into the string    


  11. Code:
    and al,0Fh; reset the older tetrad
    sub al,11h; F->FEh 1->F0h
    db 0D4h,0F9h;FE->0105h F0->00F0h
    add al,41h ;05+41->46h F0+41->31h
    stosb; put the value from AL into the string    


  12. Code:
    and al,0Fh; reset the older tetrad
    aam; 0F->105h 01->0001
    db 0D5h,11h; 105h->16h 0001->01
    add al,30h ;16+30->46h 01+30->31h
    stosb; put the value from AL into the string    


  13. Code:
    and ax,0Fh; reset the older tetrad
    aaa; 0F->105h 01->0001
    db 0D5h,11h; 105h->16h 0001->01
    add al,30h ;16+30->46h 01+30->31h
    stosb; put the value from AL into the string    


  14. Code:
    mov ecx,8
    mov bl,30h
    @@: rol eax,4
    push eax
    and al,0Fh; reset the older tetrad
    mov dl,37h
    cmp al,10
    cmovb edx,ebx
    add al,dl
    stosb; put the value from AL into the string
    pop eax
    shr eax,4; go to the next tetrad
    loop @b; decrement count    

  15. without conditional branching:
    Code:
    and al,0Fh; reset the older tetrad
    cmp al,10
    sbb ebx,ebx; if СF=0, then ebx= 0, else ebx=-1
    and ebx,-7; in ebx will 0 or -7
    lea eax,[eax+ebx+37h]
    stosb; put the value from AL into the string    


Last edited by Mikl___ on 08 Dec 2018, 15:25; edited 1 time in total
Post 05 Dec 2018, 11:00
View user's profile Send private message Visit poster's website Reply with quote
sina



Joined: 18 Aug 2003
Posts: 132
Location: istanbul turkey
sina 07 Dec 2018, 08:13
If you poke the devil Smile
Post 07 Dec 2018, 08:13
View user's profile Send private message ICQ Number Reply with quote
Mikl___



Joined: 30 Dec 2014
Posts: 143
Location: Russian Federation, Irkutsk
Mikl___ 07 Dec 2018, 12:33
Hi, sina!
Is it a compliment or sarcasm? Image
Post 07 Dec 2018, 12:33
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.