我正在编写一个用于学习目的的小引导程序。
这是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
这是我用来将其编译为原始二进制文件的Makefile
hdd.img: boot.S
as $< -o boot.o
ld --oformat binary -Ttext 0x7c00 boot.o -o hdd.img
我遇到标签没有被相对引用的问题:当加载字节时,它使用绝对地址,比如0x7c14。
所以我不能在运行时重新定位这个bootsector(例如通过在内存中进一步复制它)。如果通过与当前指令的偏移量简单引用标签会更好。
是否可以这样做?
答案 0 :(得分:1)
当然可以重新定位字符串。
首先,您的-Ttext 0x7C00
是正确的。不要改变它。
在引导加载程序的开头,您应该将段寄存器归零(%ds
,%es
,%fs
,%gs
和%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
接下来,您应该设置一个堆栈。阅读:osdev wiki about stacks
现在问你的问题:
通常以%ds:%si
的形式使用segmentation来处理字符串。重新定位引导加载程序时,只需正确更改%ds
即可
假设你调用字符串label
:
mov $label, %si // Always prefix a label address with a $
您可以使用lodsb
指令从字符串中获取字符( LO a D S tring B yte,会自动为您增加%si
:
lodsb // Character is stored in `%al` now
另一个建议是不要手动处理视频内存。使用BIOS Interrupt 0x10。
祝你的bootloader好运!