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?
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.