'Printing hex from dx with nasm

I actually want to print the content of the dx register with nasm. Thereby the content is a 16 bit hex digit such as 0x12AB.

Therefore I've first implemented a function which is able to print a string:

print_string:
    pusha
    mov ah, 0xe

print_character:
    mov al, [bx]
    inc bx
    or al, al
    jz print_done
    int 0x10
    jmp print_character

print_done:
    popa
    ret

You can use this function in this way:

mov bx, MSG
call print_string

MSG:
    db 'Test',0

Now i want to have a function, which converts the hex to a string, so that print_string is capable to print it. I was thinking about something like that:

print_hex:
    pusha
    mov bx, HEX_OUT
    ; HEX_OUT is a kind of template string
    ; now i want to get the hex of dx into this template in order to be able to print it
    ; However I'm not sure how to manage this
    call print_string
    popa
    ret

HEX_OUT:
    db '0x0000', 0

Unfortunately I'm not sure how I get the hex from dx into bx, respectively the HEX_OUT. Can someone help me or does someone have an idea?

I want to use it at the end like this:

mov dx, 0x12AA
call print_hex

Thanks you already in advance!

UPDATE:

As mentioned I could achieve the separating and printing like this:

print_hex:
    pusha
    mov bx, PREFIX
    call print_string

next_character:
    mov bx, dx
    and bx, 0xf000
    shr bx, 4
    add bh, 0x30
    cmp bh, 0x39
    jg add_7

print_character_hex:
   mov al, bh
   mov ah, 0x0e
   int 0x10
   shl dx, 4
   or dx, dx
   jnz next_character
   popa
   ret

add_7
   add bh, 0x7
   jmp print_character_hex

PREFIX:
   db '0x', 0

I tried something like this to print it with my function and the buffer:

print_hex:
    ;Added this here    
    mov cx, HEX_OUT + 2

print_character_hex:
    mov [cx], bh

Though I can't assemble this due to "invalid effective address". What do I need to do in order to accomplish this?



Solution 1:[1]

All right, I was able to manage it. Thank you for your help! Here is the working code:

print_hex:
   pusha
   mov si, HEX_OUT + 2

next_character:
  mov bx, dx
  and bx, 0xf000
  shr bx, 4
  add bh, 0x30
  cmp bh, 0x39
  jg add_7

add_character_hex:
  mov al, bh
  mov [si], bh
  inc si
  shl dx, 4
  or dx, dx
  jnz next_character
  mov bx, HEX_OUT
  call print_string
  popa
  ret

add_7:
  add bh, 0x7
  jmp add_character_hex

HEX_OUT:
  db '0x0000', 0

Solution 2:[2]

This adapts the accepted answer to include Kyle G.'s fix for the 0 issue.

; vim: :set ft=nasm:

[bits 16]

; subroutine to print a hex number.
;
; ```
; dx = the hexadecimal value to print
; ```
;
; Usage
;
; ```
; mov dx, 0x1fb6
; call print_hex
; ```
;
; used as an answer here: https://stackoverflow.com/a/27686875/7132678
;
print_hex:
        ; push all registers onto the stack
        pusha

        ; use si to keep track of the current char in our template string
        mov si, HEX_OUT + 2

        ; start a counter of how many nibbles we've processed, stop at 4
        mov cx, 0

next_character:
        ; increment the counter for each nibble
        inc cx

        ; isolate this nibble
        mov bx, dx
        and bx, 0xf000
        shr bx, 4

        ; add 0x30 to get the ASCII digit value
        add bh, 0x30

        ; If our hex digit was > 9, it'll be > 0x39, so add 7 to get
        ; ASCII letters
        cmp bh, 0x39
        jg add_7

add_character_hex:
        ; put the current nibble into our string template
        mov [si], bh

        ; increment our template string's char position
        inc si

        ; shift dx by 4 to start on the next nibble (to the right)
        shl dx, 4

        ; exit if we've processed all 4 nibbles, else process the next
        ; nibble
        cmp cx, 4
        jnz next_character
        jmp _done

_done:
        ; copy the current nibble's ASCII value to a char in our template
        ; string
        mov bx, HEX_OUT

        ; print our template string
        call print_string

        ; pop all arguments
        popa

        ; return from subroutine
        ret

add_7:
        ; add 7 to our current nibble's ASCII value, in order to get letters
        add bh, 0x7

        ; add the current nibble's ASCII
        jmp add_character_hex

; our global template string. We'll replace the zero digits here with the
; actual nibble values from the hex input.
HEX_OUT:
        db '0x0000', 0

Also, worth noting that this is an exercise from https://www.cs.bham.ac.uk/~exr/lectures/opsys/10_11/lectures/os-dev.pdf, section 3.5.1, question 5, page 23.

Solution 3:[3]

You can use this code to print a hex number

mov cx,12
  mov dx,1f34h 
  st: 
   push dx
   shr dx,cl  
   and dl,15
  print:
  add dl, 0x30 
  cmp dl, 0x39 
  jle go
  add dl, 0x7  
  go:
  mov ah, 0x2
  int 0x21  
  sub cl,4  
  pop dx  
  cmp cl,0
  jl end_code
  jmp st
  end_code:

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 fr33g
Solution 2
Solution 3 Peter Cordes