无效的基本/索引表达式

时间:2015-12-17 22:35:41

标签: assembly x86 gas 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$

产生以下错误:

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位实模式下也是如此?

2 个答案:

答案 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字节中。这不会留下太多空间。