flat assembler
Message board for the users of flat assembler.

 Index > DOS > efficient register value to ascii conversion routine
Author
 Thread
sina

Joined: 18 Aug 2003
Posts: 132
Location: istanbul turkey
sina
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?
04 Dec 2018, 10:53
Tomasz Grysztar

Joined: 16 Jun 2003
Posts: 7797
Location: Kraków, Poland
Tomasz Grysztar
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    ```
04 Dec 2018, 14:01
sina

Joined: 18 Aug 2003
Posts: 132
Location: istanbul turkey
sina
well, you ask for something and god answers

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

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
```
05 Dec 2018, 07:12
TightCoderEx

Joined: 14 Feb 2013
Posts: 58
Location: Alberta
TightCoderEx
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
05 Dec 2018, 09:56
sina

Joined: 18 Aug 2003
Posts: 132
Location: istanbul turkey
sina
thanks for the effort
well to be honest, I love the hex table and xlatb approach
05 Dec 2018, 10:11
Tomasz Grysztar

Joined: 16 Jun 2003
Posts: 7797
Location: Kraków, Poland
Tomasz Grysztar
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.)
05 Dec 2018, 10:24
Mikl___

Joined: 30 Dec 2014
Posts: 117
Mikl___
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
05 Dec 2018, 11:00
sina

Joined: 18 Aug 2003
Posts: 132
Location: istanbul turkey
sina
If you poke the devil
07 Dec 2018, 08:13
Mikl___

Joined: 30 Dec 2014
Posts: 117
Mikl___
Hi, sina!
Is it a compliment or sarcasm?
07 Dec 2018, 12:33
 Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First

 Jump to: Select a forum Official----------------AssemblyPeripheria General----------------MainTutorials and ExamplesDOSWindowsLinuxUnixMenuetOS Specific----------------MacroinstructionsOS ConstructionIDE DevelopmentProjects and IdeasNon-x86 architecturesHigh Level LanguagesProgramming Language DesignCompiler Internals Other----------------FeedbackHeapTest Area

Forum Rules:
 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot vote in polls in this forumYou cannot attach files in this forumYou can download files in this forum

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

Website powered by rwasa.