Question

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
Was it helpful?

Solution

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!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top