Assembly - Printing 16-bit addresses

21 Nov 2023

To accompany my recent dive into writing in assembly, this blog post will explain a routine I wrote that is able to print 16 bit addresses.

The function originates from developing a small operating system. Just in the beginning of it, I needed to find a nice way to print addresses, without invoking the debugger. This routine uses BIOS functions in real mode and thus looks best inside a 512 byte sized bootloader.

mov bx, LOOKUP_TABLE    ; prepare for xlat
mov dx, 0xfab1          ; address that'll be printed
mov si, 0x4
mov ah, 0x0e

parse_hex:
  mov al, dh            ; copy the first byte to work on it
  and al, 0xf0          ; select the first nibble (one hex digit)
  shr al, 4             ; shift right; put digit in place for xlat
  xlat                  ; mov al, ds:[bx+al]
  int 0x10              ; print content of al
  rol dx, 4             ; byte rotate left; next digit in address
  dec si
  cmp si, 0
  jne parse_hex

LOOKUP_TABLE: db '0123456789abcdef', 0
The comments in the code above already explain it, but xlat needs a more in depth explanation. The instruction copies the contents of one register to another that can be modified with a value of distance in memory. In the case of the given digit 'f' and the LOOKUP_TABLE starting at memory address 0x7c1e, the task is to append the given digit to the memory address to get the correct ascii value. The content of the lookup table looks in memory looks like this (little-endian):
0x7c1e:  0x33323130  0x37363534 0x62613938 0x66656463
                                              ^ 0x7c2d
In this example 66 would be stored into al. The next instruction would then convert the digits back to the ascii value 'f' and print it to the console.