问题
I am writing a little bootsector for learning purpose.
Here is boot.S
.code16
.text
movw $0xB800, %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 $0x07, %es:0x1 /* white on black */
jmp .
label:
.byte 'A
.=510
.byte 0x55
.byte 0xAA
and here is the Makefile I use to compile it to a raw binary file
hdd.img: boot.S
as $< -o boot.o
ld --oformat binary -Ttext 0x7c00 boot.o -o hdd.img
I face the problem that the label is not relatively referenced: when loading the byte 'A', it uses the absolute address, say 0x7c14).
So I cannot relocate this bootsector at runtime (for example by copying it further in memory). It would be better if the label was simply referenced trough an offset from the current instruction.
Is it possible to do this ?
回答1:
Of course it is possible to relocate strings.
First of all, your -Ttext 0x7C00
is correct. Do not change it.
At the beginning of your bootloader you should zero the segment registers (%ds
, %es
, %fs
, %gs
and %ss
):
mov $0, %ax // xor %ax, %ax would be more space efficient
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
Next, you should set up a stack. Read: osdev wiki about stacks
Now to your question:
It is usual to address strings using segmentation in the form of %ds:%si
. When relocating the bootloader, just change %ds
properly.
Assuming you call your string label
:
mov $label, %si // Always prefix a label address with a $
You can get a character from a string using the lodsb
instruction (LOaD String Byte, which automatically increments %si
for you:
lodsb // Character is stored in `%al` now
Another recommendation is not to address the video memory manually. Use BIOS Interrupt 0x10.
Good luck with your bootloader!
来源:https://stackoverflow.com/questions/28740677/gnu-gas-label-is-not-relatively-referenced