I am practicing to write a bootstrap using assembly (in AT&T syntax, and gnu/gas). The small program is assembled and linked, then copied to the first sector of a virtual disk. BIOS will load it into 0000:7c00
, and here comes the problem. The call hello
will be translated from call 0010
to call 7c10
during running. But the movw $message, %as
doesn't get relocated. The ax
is still 0026
, not 7c26
. The result is that I can't make the Hello World
on the screen. Instead, some random data at 0000:0026
will be displayed on the screen.
How can I make it correct during booting? Should I change the asm source code using some directives? Or should I change my link script?
Thank you!
.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
I use the following assemble and link scripts
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
I see that the main problem is in the way you are compiling your code.
The correct steps to get your code working should be:
as boot.s -c -o boot.o
ld --oformat binary --Ttext 0x7C00 -o boot.bin boot.o
Please note, as others have said, that I'm passing the --Ttext 0x7C00
parameter to ld
, to force it relocating your code at that address.
As an additional suggestion, try to structure your code like this:
.text
.global _start
.code16
_start:
jmp stage1_start
...
stage1_start:
<your bootloader here>
Note that this is compiant with how BIOS code looks at hard drives, since after 2 bytes (the length of the first jump instruction) you should place the Disk Description Table.
Additionally, you can refactor your last instructions in a more as
-like syntax like this:
. = _start + 0x0200 - 2
.short 0x0AA55
Where the .
variable is the location counter. Look at this page for further information on how this counter works (in the context of ld
, not as
).
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With