Search code examples
assemblyreal-mode

32-bit registers in real mode and dereferencing


I'm writing some assembly for MBR (real mode). I know that in real mode you can't use the 32-bit registers, only the 16-bit ones.

I wrote this code which relies on a print_char function.

    mov ecx, MSG
write:
    mov al, [ecx]
    cmp al, 0x0
    je end_print
    call print_char
    inc cx
    jmp write
end_print:
    ret
MSG: db 'Hi!', 0xd, 0xa, 0x0

This code doesn't compile due to the reason:

error: invalid effective address

I use

nasm -f bin -o out src.s

When I change the register name to ecx, the code starts to compile, and surprisingly, works.

Why does my code using 32-bit registers work in real mode and why does using 16-bit registers not?


Solution

  • The x86 ISA supports a number of addressing modes. There are two sets of addressing modes, one for 16 bit mode and one for 32 bit mode.

    In 32 bit mode, you can use indexed addressing with any register and the three-part SIB addressing.

    In 16 bit mode, only the following addressing modes exist (each with optional displacement):

    BX + disp
    BX + SI + disp
    BX + DI + disp
    BP + disp
    BP + SI + disp
    BP + DI + disp
    SI + disp
    DI + disp
    disp
    

    Note how cx isn't available as an index register.

    What you can do to get around this problem is to use a 32 bit addressing mode in 16 bit mode. This is done by specifying ecx as an index register as you did.