5

我正在练习使用程序集(在 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
4

1 回答 1

1

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

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

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, not的上下文中as)。

希望这可以帮助!

于 2012-10-09T21:13:25.247 回答