Need Help Debugging Assembly xlatb Hex Converter Program

I’m brand new to assembly and I’m trying to write a program that reads a character and prints its ASCII code in hex. I’m using NASM on Linux, but I keep getting errors. Here’s my code:

section .data
    char_prompt db "Please input a character: ",0
    out_msg1 db "The ASCII code of '",0
    out_msg2 db "' in hex is ",0
    query_msg db "Do you want to quit (Y/N): ",0
    hex_table db "0123456789ABCDEF",0

section .bss
    ; no variables needed

section .text
    global _start

_start:
    ; prompt for character
    mov eax, 4          ; sys_write
    mov ebx, 1          ; stdout
    mov ecx, char_prompt
    mov edx, 24
    int 0x80

    ; read character
    mov eax, 3          ; sys_read
    mov ebx, 0          ; stdin
    lea ecx, [esp-1]    ; temporary buffer on stack
    mov edx, 1
    int 0x80
    mov al, [ecx]       ; get the character

    ; output first message
    mov eax, 4
    mov ebx, 1
    mov ecx, out_msg1
    mov edx, 18
    int 0x80

    ; output the character itself
    mov eax, 4
    mov ebx, 1
    lea ecx, [esp-1]   ; reuse buffer with the character
    mov edx, 1
    int 0x80

    ; output second message
    mov eax, 4
    mov ebx, 1
    mov ecx, out_msg2
    mov edx, 15
    int 0x80

    ; convert to hex using xlatb
    mov ah, al          ; save character in ah
    mov ebx, hex_table  ; load table address
    shr al, 4           ; get high nibble
    xlatb               ; replace al with hex digit
    ; output high nibble
    push eax
    mov eax, 4
    mov ebx, 1
    lea ecx, [esp]      ; address of the digit on stack
    mov edx, 1
    int 0x80
    pop eax

    mov al, ah          ; restore character
    and al, 0x0F        ; get low nibble
    xlatb
    ; output low nibble
    push eax
    mov eax, 4
    mov ebx, 1
    lea ecx, [esp]
    mov edx, 1
    int 0x80
    pop eax

    ; newline
    mov eax, 4
    mov ebx, 1
    mov ecx, newline
    mov edx, 1
    int 0x80

    ; query to quit
    mov eax, 4
    mov ebx, 1
    mov ecx, query_msg
    mov edx, 20
    int 0x80

    ; read reply
    mov eax, 3
    mov ebx, 0
    lea ecx, [esp-1]
    mov edx, 1
    int 0x80
    mov al, [ecx]

    cmp al, 'Y'
    jne _start          ; if not 'Y', read another character

    ; exit
    mov eax, 1
    xor ebx, ebx
    int 0x80

section .data
    newline db 0x0A

But I’m getting an error: “error: invalid combination of opcode and operands” on the mov ebx, hex_table line. Can anyone help? The original code I found used a different syntax and I’m not sure what’s wrong.

:movie_camera: Video Tutorial:

:books: Official Documentation & Reference Links:

Angela,

The issue is that you’re trying to move the value of hex_table into EBX, but you actually need the address of the table. The xlatb instruction expects EBX to hold the base address of the translation table. In your code, mov ebx, hex_table is interpreted as moving the first 4 bytes of the table (which is “0123”) into EBX, which is a number, not an address. That causes the assembler to complain because the operand size mismatch (hex_table is a byte array, EBX is 32-bit).

You should use the lea (Load Effective Address) instruction to get the address:

lea ebx, [hex_table]

Alternatively, you can use mov ebx, hex_table if you define hex_table as a label and let the assembler handle it, but in NASM that already gives the address. However, you might be mixing syntax from different assemblers. In NASM, mov ebx, hex_table does give the address (since hex_table is a label), but the error you saw suggests your code might have been using a different assembler or a problematic directive.

Check your original code: you had hex-table with a hyphen instead of an underscore. That might have caused the label not to be recognized properly. Also, your hex table string “012345789ABCDEF” is missing the digit ‘6’ after ‘5’? It should be “0123456789ABCDEF”.

Let me know if you need more help. I’ve been using assembly for about 3 years, and I find it really improves your problem-solving skills once you get past the initial frustration.

Angela,

I saw that you figured out the hyphen/underscore issue – good catch! That’s a classic mistake. Just to expand on ghostrider’s advice, here’s a cleaned-up version of your program using modern NASM syntax. I also corrected the hex table spelling and used lea as suggested:

section .data
    char_prompt db "Please input a character: ",0
    out_msg1 db "The ASCII code of '",0
    out_msg2 db "' in hex is ",0
    query_msg db "Do you want to quit (Y/N): ",0
    hex_table db "0123456789ABCDEF",0
    newline db 0x0A,0

section .text
    global _start

_start:
    ; prompt
    mov eax, 4
    mov ebx, 1
    mov ecx, char_prompt
    mov edx, 24
    int 0x80

    ; read character
    sub esp, 2
    mov eax, 3
    mov ebx, 0
    lea ecx, [esp]
    mov edx, 1
    int 0x80
    mov al, [esp]

    ; output first part
    mov eax, 4
    mov ebx, 1
    mov ecx, out_msg1
    mov edx, 18
    int 0x80

    ; output the character
    mov eax, 4
    mov ebx, 1
    lea ecx, [esp]
    mov edx, 1
    int 0x80

    ; output second part
    mov eax, 4
    mov ebx, 1
    mov ecx, out_msg2
    mov edx, 15
    int 0x80

    ; convert and output high nibble
    mov ah, al
    lea ebx, [hex_table]
    shr al, 4
    xlatb
    mov [esp], al
    mov eax, 4
    mov ebx, 1
    lea ecx, [esp]
    mov edx, 1
    int 0x80

    ; low nibble
    mov al, ah
    and al, 0x0F
    xlatb
    mov [esp], al
    mov eax, 4
    mov ebx, 1
    lea ecx, [esp]
    mov edx, 1
    int 0x80

    ; newline
    mov eax, 4
    mov ebx, 1
    mov ecx, newline
    mov edx, 1
    int 0x80

    ; query
    mov eax, 4
    mov ebx, 1
    mov ecx, query_msg
    mov edx, 20
    int 0x80

    ; read reply
    mov eax, 3
    mov ebx, 0
    lea ecx, [esp]
    mov edx, 1
    int 0x80
    mov al, [esp]

    cmp al, 'Y'
    jne _start

    ; exit
    add esp, 2
    mov eax, 1
    xor ebx, ebx
    int 0x80

Also, make sure you assemble and link with:

nasm -f elf32 program.asm -o program.o
ld -m elf_i386 program.o -o program

Once you get the hang of it, assembly becomes a really powerful tool for understanding how computers work at the lowest level. Keep at it!