无效的 base/index 表达式
Invalid base/index expressions
尝试使用基本索引表达式在 16 位实模式下操作内存会导致编译错误:
movw [=11=]xd000, -2(%sp)
movw [=11=], -4(%sp)
movw , -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 位的寻址模式寄存器选择非常有限。参见 https://whosebug.com/tags/x86/info / 。
[reg1 + reg2 + displacement]
的任何子集都有效,其中reg1
可以是BX或BP,and/or reg2
可以是SI或DI。
16bit 不能使用 SIB 字节,所以所有 1 和 2 reg 寻址模式都必须编码到 mod/rm 字节中。这样就没有多少空间了。
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 位寻址。
但是,您的尝试仍然存在根本性问题。您正试图将值存储在堆栈指针下方的地址。这些地址将被未来的推送和调用覆盖,并且不可预测地被中断覆盖。即使您已禁用中断并且未使用任何使用堆栈的指令,在堆栈上为您正在使用的内存正确分配 space 仍然是一个好主意。
例如:
movw %sp, %bp
subw , %sp
movw [=10=]xd000, -2(%bp)
movw [=10=], -4(%bp)
movw , -6(%bp)
尝试使用基本索引表达式在 16 位实模式下操作内存会导致编译错误:
movw [=11=]xd000, -2(%sp)
movw [=11=], -4(%sp)
movw , -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 位的寻址模式寄存器选择非常有限。参见 https://whosebug.com/tags/x86/info /
[reg1 + reg2 + displacement]
的任何子集都有效,其中reg1
可以是BX或BP,and/or reg2
可以是SI或DI。
16bit 不能使用 SIB 字节,所以所有 1 和 2 reg 寻址模式都必须编码到 mod/rm 字节中。这样就没有多少空间了。
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 位寻址。
但是,您的尝试仍然存在根本性问题。您正试图将值存储在堆栈指针下方的地址。这些地址将被未来的推送和调用覆盖,并且不可预测地被中断覆盖。即使您已禁用中断并且未使用任何使用堆栈的指令,在堆栈上为您正在使用的内存正确分配 space 仍然是一个好主意。
例如:
movw %sp, %bp
subw , %sp
movw [=10=]xd000, -2(%bp)
movw [=10=], -4(%bp)
movw , -6(%bp)