如何在 AT&T 汇编中正确定位变量?
-
11-12-2019 - |
题
我正在练习使用程序集(使用 AT&T 语法和 gnu/gas)编写引导程序。小程序被组装和链接,然后复制到虚拟磁盘的第一个扇区。BIOS 会将其加载到 0000:7c00
, ,问题来了。这 call hello
将翻译自 call 0010
到 call 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
).
希望这可以帮助!
不隶属于 StackOverflow