4

尝试使用基索引表达式在 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 位实模式下?

4

2 回答 2

5

SP 在 16 位寻址模式中不能用作基址或索引寄存器。与 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)
于 2015-12-17T22:57:43.937 回答
0

16 位寻址模式的寄存器选择非常有限。请参阅https://stackoverflow.com/tags/x86/info /引用内存位置的内容。(x86 寻址模式)

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

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

于 2015-12-17T22:57:15.707 回答