1

I am trying to write a library function in 8086 assembly that will dump the contents of the registers as hex values, but my code doesn't appear to be working right and I don't know why. The basic strategy is to shift the register to be dumped right by 12, 8, 4 and 0 and use the value in the low byte of the register to index into a table of hex characters. The code works for the first digit, but it prints nothing (or an invisible character) for the second digit. Here's my code:

hex_tbl:
    db  '0123456789ABCDEF'

print_tbl:
    mov bx, hex_tbl
    
    mov dx, 0x9FFF     ; Value to be printed
    push dx
    
    shr dx, 12
    add bl, dl
    mov ax, [bx]
    sub bl, dl
    call display_letter
    
    pop dx
    shr dx, 8
    add bl, dl
    mov ax, [bx]
    sub bl, dl
    call display_letter
    
    ret

    ; Display letter in AL (ASCII code)
display_letter:
    push ax
    push bx
    push cx
    push dx
    push si
    push di
    mov ah, 0x0e    ; Load AH with code for terminal output
    mov bx, 0x000f  ; Load BH page zero and BL color (graphic mode)
    int 0x10        ; Call the BIOS for displaying one letter
    pop di
    pop si
    pop dx
    pop cx
    pop bx
    pop ax
    ret             ; Returns to caller

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
M. Gianota
  • 184
  • 8
  • 1
    You need to isolate nibbles for your LUT to work. The top one gets isolated for free by `shr dx, 12` shifting in zeros; the others need an `and dl, 0xf`. And you're not even trying to print the bottom two. Also, if you use SI instead of DX, you can use `[bx+si]` instead of wasting instructions on address math. Anyway, [Converting bin to hex in assembly](https://stackoverflow.com/q/40818086) has working asm that shows how to `and` away other bits. It uses `xlat` instead of `mov` so the 4-bit integer goes in AL instead of SI or DI. It of course uses a loop for 4 hex digits. – Peter Cordes Feb 21 '22 at 21:08
  • 2
    If you want to see why exactly yours didn't work, single-step with a debugger and look at `dl` and `bx` when `mov ax, [bx]` runs. And BTW, you forgot `align 16` for your `hex_tbl:` Adding just the low bytes of the address could wrap (without carry into the high byte of the address) if the table started in the last 15 bytes of a 256-byte region. i.e. at an address >= `0x??F1`. Aligning by 16 makes sure that can't happen. – Peter Cordes Feb 21 '22 at 21:14

0 Answers0