Assembly 基/索引表达式无效

Assembly 基/索引表达式无效,assembly,x86,gnu-assembler,real-mode,Assembly,X86,Gnu Assembler,Real Mode,尝试使用基索引表达式在16位实模式下操作内存会导致编译错误: movw $0xd000, -2(%sp) movw $0, -4(%sp) movw $1, -6(%sp) 编撰 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$ 产生以下错误: boots

尝试使用基索引表达式在16位实模式下操作内存会导致编译错误:

movw    $0xd000, -2(%sp)
movw    $0, -4(%sp)
movw    $1, -6(%sp)
编撰

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$
产生以下错误:

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

我认为这是有效的语法,即使在16位实模式下也是如此?

16位寻址模式的寄存器选择非常有限。见/

[reg1+reg2+displacement]
的任何子集都有效,其中
reg1
可以是BX或BP,和/或
reg2
可以是SI或DI


16位不能使用SIB字节,因此所有一个和两个reg寻址模式都必须编码到mod/rm字节中。这并没有留下太多空间。

在16位寻址模式下,SP不能用作基址或索引寄存器。与32位寻址模式不同,允许的模式对于可以使用的寄存器非常有限

您仅限于以下模式:
(%bx)
(%bp)
(%si)
(%di)
(%bx,%si)
(%bx,%di)
(%bp,%si)
(%bp,%di)
。这些都可以有可选的8位或16位位移。(严格来说,
(%bp)
必须有位移,但如果不提供位移,汇编程序将使用0位移)注意,使用bp作为基的寻址模式也默认为堆栈段(SS)而不是数据段(DS)

在您的情况下,部分解决方案是使用BP作为基础,首先从SP复制值。或者,您可以使用ESP作为基础,因此在允许的情况下使用32位寻址

然而,你所尝试的仍然存在根本性的问题。您正在尝试将值存储在堆栈指针下面的地址。这些地址将被未来的推送和调用以及不可预测的中断所覆盖。即使您已经禁用了中断,并且没有使用任何使用堆栈的指令,也最好在堆栈上为正在使用的内存正确分配空间

例如:

movw    %sp, %bp
subw    $6, %sp
movw    $0xd000, -2(%bp)
movw    $0, -4(%bp)
movw    $1, -6(%bp)