我正在练习使用程序集(使用 AT&T 语法和 gnu/gas)编写引导程序。小程序被组装和链接,然后复制到虚拟磁盘的第一个扇区。BIOS 会将其加载到 0000:7c00, ,问题来了。这 call hello 将翻译自 call 0010call 7c10 跑步期间。但是 movw $message, %as 不会被搬迁。这 ax 还是 0026, , 不是 7c26. 。结果是我做不到 Hello World 屏幕上。相反,一些随机数据 0000:0026 将显示在屏幕上。

如何在启动时使其正确?我应该使用一些指令更改 asm 源代码吗?或者我应该更改我的链接脚本?

谢谢你!

.text
.global     _start
.code16

_start:
movw    %cs, %ax
movw    %ax, %ds
movw    %ax, %es
call    hello
jmp     .

.org    0x10

hello:
movw    $message, %ax
movw    %ax, %bp
movw    $13, %cx
movw    $0x1301, %ax
movw    $0x000c, %bx
movb    $0, %dl
int     $0x10
ret

message:    
.ascii  "Hello, World!"

.org    0x01fe
.byte   0x55
.byte   0xaa

我使用以下汇编和链接脚本

as -o boot.o boot.s  
    //generate object code

ld -Ttext 0x0 -e _start -s -o boot.out boot.o  
    //relocate .text to 0x0
    //entry is _start

objcopy -O binary -j .text boot.out boot
    //copy .text section to boot

vboxmanage convertfromraw boot boot.vdi --format VDI
    //create vdi for virtual box
有帮助吗?

解决方案

我发现主要问题在于您编译代码的方式。

让代码正常工作的正确步骤应该是:

as boot.s -c -o boot.o
ld --oformat binary --Ttext 0x7C00 -o boot.bin boot.o

请注意,正如其他人所说,我正在通过 --Ttext 0x7C00 参数为 ld, ,强制它将您的代码重新定位到该地址。

作为附加建议,请尝试按如下方式构建代码:

.text
.global     _start
.code16

_start:
jmp stage1_start

...

stage1_start:

<your bootloader here>

请注意,这与 BIOS 代码如何看待硬盘驱动器一致,因为在 2 个字节(第一个跳转指令的长度)之后,您应该放置磁盘描述表。

此外,您可以在更多内容中重构最后的指令 as像这样的语法:

. = _start + 0x0200 - 2
.short 0x0AA55

哪里的 . 变量是位置计数器。看着 这一页 有关此计数器如何工作的更多信息(在 ld, , 不是 as).

希望这可以帮助!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top