Assembly 基/索引表达式无效
尝试使用基索引表达式在16位实模式下操作内存会导致编译错误: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
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)