Max*_*nov 4 x86 assembly real-mode gnu-assembler
尝试使用基索引表达式在 16 位实模式下操作内存会导致编译错误:
movw $0xd000, -2(%sp)
movw $0, -4(%sp)
movw $1, -6(%sp)
Run Code Online (Sandbox Code Playgroud)
编译为
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$
Run Code Online (Sandbox Code Playgroud)
产生以下错误:
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
Run Code Online (Sandbox Code Playgroud)
我认为这是有效的语法,即使在 16 位实模式下也是如此?
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)
Run Code Online (Sandbox Code Playgroud)