GNU GAS:标签未被相对引用

GNU GAS: Label is not relatively referenced

我正在写一个小引导扇区用于学习目的。

这里是boot.S

.code16
.text
    movw    [=10=]xB800, %ax    /* 0xB000 is the text screen video memory */
    movw    %ax, %es       /* set it as the %es segment */

    movb    label, %al
    movb    %al, %es:0x0    /* screen[0] = 'A' */
    movb    [=10=]x07, %es:0x1  /* white on black */
    jmp .

label:  
    .byte 'A

    .=510
    .byte 0x55
    .byte 0xAA

这是我用来将其编译为原始二进制文件的 Makefile

hdd.img: boot.S
    as $< -o boot.o
    ld --oformat binary -Ttext 0x7c00 boot.o -o hdd.img

我遇到标签没有相对引用的问题:加载字节'A'时,使用的是绝对地址,比如0x7c14)。

所以我不能在运行时重新定位这个引导扇区(例如通过在内存中进一步复制它)。如果通过当前指令的偏移量简单地引用标签会更好。

可以这样做吗?

当然可以重新定位字符串。

首先,你的-Ttext 0x7C00是正确的。不要改变它。 在引导加载程序的开头,您应该将段寄存器(%ds%es%fs%gs%ss)归零:

mov [=10=], %ax         // xor %ax, %ax would be more space efficient
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss

接下来,您应该设置堆栈。阅读:osdev wiki about stacks

现在回答你的问题: 通常使用 %ds:%si 形式的 segmentation 来寻址字符串。重新定位引导加载程序时,只需适当更改%ds即可。
假设你调用你的字符串 label:

mov $label, %si     // Always prefix a label address with a $

你可以使用lodsb指令从字符串中获取一个字符(LOaD String Byte,自动递增%si给你:

lodsb               // Character is stored in `%al` now

另一个建议是不要手动寻址显存。使用 BIOS Interrupt 0x10.

祝你的引导加载程序好运!