Skip to content

Instantly share code, notes, and snippets.

@jsutlovic
Created October 7, 2014 03:52
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save jsutlovic/7f1c5629deef4543bb47 to your computer and use it in GitHub Desktop.
Save jsutlovic/7f1c5629deef4543bb47 to your computer and use it in GitHub Desktop.
Assembly print hex
[org 0x7c00]
mov dx, 0x1fb7 ; Set the value we want to print to dx
call print_hex ; Print the hex value
jmp $ ; Hang once we're done
%include "print_string.asm"
; Prints the value of DX as hex.
print_hex:
pusha ; save the register values to the stack for later
mov cx,4 ; Start the counter: we want to print 4 characters
; 4 bits per char, so we're printing a total of 16 bits
char_loop:
dec cx ; Decrement the counter
mov ax,dx ; copy bx into ax so we can mask it for the last chars
shr dx,4 ; shift bx 4 bits to the right
and ax,0xf ; mask ah to get the last 4 bits
mov bx, HEX_OUT ; set bx to the memory address of our string
add bx, 2 ; skip the '0x'
add bx, cx ; add the current counter to the address
cmp ax,0xa ; Check to see if it's a letter or number
jl set_letter ; If it's a number, go straight to setting the value
add byte [bx],7 ; If it's a letter, add 7
; Why this magic number? ASCII letters start 17
; characters after decimal numbers. We need to cover that
; distance. If our value is a 'letter' it's already
; over 10, so we need to add 7 more.
jl set_letter
set_letter:
add byte [bx],al ; Add the value of the byte to the char at bx
cmp cx,0 ; check the counter, compare with 0
je print_hex_done ; if the counter is 0, finish
jmp char_loop ; otherwise, loop again
print_hex_done:
mov bx, HEX_OUT ; print the string pointed to by bx
call print_string
popa ; pop the initial register values back from the stack
ret ; return the function
; global variables
HEX_OUT: db '0x0000',0
; Padding and magic number
times 510-($-$$) db 0
dw 0xaa55
print_string: ; Push registers onto the stack
pusha
string_loop:
mov al, [bx] ; Set al to the value at bx
cmp al, 0 ; Compare the value in al to 0 (check for null terminator)
jne print_char ; If it's not null, print the character at al
; Otherwise the string is done, and the function is ending
popa ; Pop all the registers back onto the stack
ret ; return execution to where we were
print_char:
mov ah, 0x0e ; Linefeed printing
int 0x10 ; Print character
add bx, 1 ; Shift bx to the next character
jmp string_loop ; go back to the beginning of our loop
@tanzercakir
Copy link

This function works well , for one reason i have to write "string_reset" function because the string HEX_OUT changed after recalling print_hex. This function resets HEX_OUT to "0x0000" again for later print_hex calls.Call this "string_reset" function in print_hex_done section immediately after "call print_string" statement.

string_reset :  
pusha
mov bx , HEX_OUT
add bx , 2 ;start after 0x

start :
cmp byte [bx],0 ; while not 0
jne set ; put 0 as ASCII string
jmp finish

set:

mov byte [bx] , 0x30

inc bx

jmp start

finish: ;function ends

popa

ret

@radovicmare
Copy link

Greetings,
I am new to assembly and I was trying to figure this out, however it seems to me this code skips the first nibble and immediately goes to right shift...
Could someone more knowledgeable than me give me some insight?
Thanks!

p.s. I've already written this code differently and it works without affecting the initial HEX_OUT, I'm asking out of curiosity because I don't want to miss something in this early stage of learning asm...

@kthompson
Copy link

I have updated the function here https://gist.github.com/kthompson/957c635d84b7813945aa9bb649f039b9 so that it is not required to reset the HEX_OUT variable each time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment