Trying to use base-index expressions to manipulate memory in 16-bit real mode results in compilation errors:
movw $0xd000, -2(%sp)
movw $0, -4(%sp)
movw $1, -6(%sp)
Compiled with
gcc -c -Wa,--32 $(DIR_BS_SRC)/mbr.S -o $(DIR_BS_SRC)/mbr.o
ld -nostdlib --oformat binary --Ttext 0x7c00 $(DIR_BS_SRC)/mbr.o -o $(DIR_B$
produces the following errors:
bootsector/src/mbr.S:20: Error: `-2(%sp)' is not a valid base/index expression
bootsector/src/mbr.S:21: Error: `-4(%sp)' is not a valid base/index expression
bootsector/src/mbr.S:22: Error: `-6(%sp)' is not a valid base/index expression
I thought this was valid syntax, even in 16 bit real mode?
SP can't be used as a base or index register in the 16-bit addressing modes. Unlike the 32-bit addressing modes the allowed modes are very restricted as to what registers can be used.
You're limited to the following modes (%bx)
, (%bp)
, (%si)
, (%di)
, (%bx,%si)
, (%bx,%di)
, (%bp,%si)
and (%bp,%di)
. These can all have an optional 8-bit or 16-bit displacement. (Strictly speaking (%bp)
must have displacement, but the assembler will use a 0 displacement if you don't provide one) Note that the addressing modes that use BP as a base also default to the stack segment (SS) rather than data segment (DS).
A partial solution in your case would be to use BP as your base instead, copying the value from SP first. Alternatively you could use ESP as your base and so use 32-bit addressing where it's allowed.
However there would be still be fundamental problem with what you're attempting. You're trying to store values at addresses below the stack pointer. These addresses will be overwritten by future pushes and calls, and unpredictably by interrupts. Even you've disabled interrupts and are not using any instructions that use the stack, it would still be a good idea to properly allocate the the space on the stack for the memory you're using.
For example:
movw %sp, %bp
subw $6, %sp
movw $0xd000, -2(%bp)
movw $0, -4(%bp)
movw $1, -6(%bp)