Mezbaul
Mezbaul

Reputation: 1272

why does this bootloader only prints 'S'

I am writing a simple x86 bootloader.

this is the c program that im having trouble with: test4.c

__asm__(".code16\n");
__asm__("jmpl $0x0, $main\n");

void prints ( char* str )
{
    char* pStr = str;

    while( *pStr )
    {
        __asm__ __volatile (
            "int $0x10"
            :
            : "a"(0x0e00 | *pStr), "b"(7)
        );
        pStr++;
    }
}

void main ( ) 
{
    char*  str = "\n\rHello World\n\r";
    char* pStr = str;

    while( *pStr )
    {
        __asm__ __volatile (
            "int $0x10"
            :
            : "a"(0x0e00 | *pStr)
        );
        pStr++;
    }
    prints ( str );

}

when i try to print a string within main function, it works. But when i pass the string to another function which does carry out same instructions but still prints only S to the screen. So the final output looks something like this:

Hello World
S

Here is the linker file i used: test.ld

ENTRY(main);
SECTIONS
{
    . = 0x7C00;
    .text : AT(0x7C00)
    {
        *(.text);
    }
    .sig : AT(0x7DFE)
    {
        SHORT(0xaa55);
    }
}

Here are the commands i used to compile the c program and to link it

$ gcc -c -g -Os -m32 -march=i686 -ffreestanding -Wall -Werror test4.c -o test4.o
$ ld -melf_i386 -static -Ttest.ld -nostdlib --nmagic -o test4.elf test4.o
$ objcopy -O binary test4.elf test4.bin

and i used bochs emulator to test out this bootloader

Upvotes: 0

Views: 120

Answers (1)

user149341
user149341

Reputation:

You can't do this with GCC. Ignore all the tutorials that say that you can -- they are wrong.

What's most important to keep in mind is that GCC is not a 16-bit compiler. The __asm__(".code16\n") directive does not turn it into one; it merely confuses the assembler into retargeting GCC's output from 32-bit x86 to 16-bit. This will cause strange and unexpected behavior, especially in any code using pointers.

If you want to write an x86 bootloader, you will need to:

  • Use a C compiler that can specifically target 16-bit x86 ("real mode"). Consider the OpenWatcom toolchain, for instance.

  • Become very familiar with the quirks of x86 real mode -- particularly segmentation.

  • Write some portions of the bootloader in assembly, particularly the startup code.

Upvotes: 4

Related Questions