尝试使用基本索引表达式以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位实模式下也是如此?
答案 0 :(得分:3)
SP不能用作16位寻址模式的基址或索引寄存器。与32位寻址模式不同,允许的模式对于可以使用的寄存器非常有限。
您仅限于以下模式(%bx)
,(%bp)
,(%si)
,(%di)
,(%bx,%si)
,(%bx,%di)
,{ {1}}和(%bp,%si)
。这些都可以选择8位或16位位移。 (严格来说(%bp,%di)
必须有位移,但如果你不提供一个位移,汇编器将使用0位移。注意,使用BP作为基础的寻址模式也默认为堆栈段(SS)而不是数据段(DS)。
在您的情况下,部分解决方案是使用BP作为基础,首先从SP复制值。或者,您可以使用ESP作为基础,因此在允许的情况下使用32位寻址。
但是,您尝试的内容仍然存在根本问题。您正试图将值存储在堆栈指针下方的地址处。这些地址将被未来的推送和调用覆盖,并且会被中断无法预测。即使你已经禁用了中断并且没有使用任何使用堆栈的指令,为你正在使用的内存正确分配堆栈空间仍然是一个好主意。
例如:
(%bp)
答案 1 :(得分:0)
16位的寻址模式寄存器选择非常有限。请参阅https://stackoverflow.com/tags/x86/info / Referencing the contents of a memory location. (x86 addressing modes)。
[reg1 + reg2 + displacement]
的任何子集都有效,其中reg1
可以是BX或BP,和/或reg2
可以是SI或DI。
16位不能使用SIB字节,因此必须将所有一个和两个reg寻址模式编码到mod / rm字节中。这不会留下太多空间。