【问题标题】:Invalid base/index expressions [duplicate]无效的基本/索引表达式[重复]
【发布时间】:2015-12-17 22:35:40
【问题描述】:

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

【问题讨论】:

    标签: assembly x86 gnu-assembler real-mode


    【解决方案1】:

    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)
    

    【讨论】:

      【解决方案2】:

      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。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-02
        • 2020-06-07
        • 1970-01-01
        • 2021-12-05
        • 1970-01-01
        • 1970-01-01
        • 2020-02-11
        相关资源
        最近更新 更多