Как правильно найти переменную в сборке 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
).
Надеюсь это поможет!