如何在AT&T组件中正确定位变量?

Ste*_* Wu 5 assembly bootstrapping ld att

我正在练习使用汇编编写引导程序(在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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

ilp*_*lle 1

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

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

as boot.s -c -o boot.o
ld --oformat binary --Ttext 0x7C00 -o boot.bin boot.o
Run Code Online (Sandbox Code Playgroud)

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

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

.text
.global     _start
.code16

_start:
jmp stage1_start

...

stage1_start:

<your bootloader here>
Run Code Online (Sandbox Code Playgroud)

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

此外,您可以用更类似as的语法重构最后的指令,如下所示:

. = _start + 0x0200 - 2
.short 0x0AA55
Run Code Online (Sandbox Code Playgroud)

其中.变量是位置计数器。请参阅此页面ld以获取有关此计数器如何工作的更多信息(在,而不是的上下文中as)。

希望这可以帮助!