I tried to use below sample bootloader from Internet.
__asm__(".code16gcc\n");
__asm__ ("jmpl $0, $main\n");
#define __NOINLINE __attribute__((noinline))
#define __REGPARM __attribute__ ((regparm(3)))
#define __NORETURN __attribute__((noreturn))
/* BIOS interrupts must be done with inline assembly */
void __NOINLINE __REGPARM print(const char *s){
__asm__ __volatile__("movb %0 , %%al\n" : :"c"(*s):"memory");
//__asm__ __volatile__("movb $'W' , %al\n");
__asm__ __volatile__("movb $0x0e, %ah\n");
__asm__ __volatile__("int $0x10\n");
}
/* and for everything else you can use C! Be it traversing the filesystem, or verifying the kernel image etc.*/
void __NORETURN main(){
__asm__ __volatile__ ("movb $0x0, %al\n");
print("woo hoo!\r\n:)");
while(1);
}
For linking below basic linker script used.
ENTRY(main);
SECTIONS
{
. = 0x7C00;
.text : AT(0x7C00)
{
*(.text);
}
.sig : AT(0x7DFE)
{
SHORT(0xaa55);
}
}
I prepared a binary bootable image and copied to floppy using below commands.
gcc -c -Os -g -march=i686 -ffreestanding -Wall -Werror -I. test.c -o test.o
ld -m elf_i386 -static -Ttest.ld -nostdlib --nmagic -o test.elf test.o
objcopy -O binary test.elf test.bin
sudo dd if=test5.bin of=/dev/fd0
As we can easily notice I am trying to print character 'w' only, from the string "woo hoo!" passed to print() function. But when I tried to boot it on Virtual Machine, it did not print anything.
However if I comment 1st statement of print() and uncomment second statement, character 'W' is printed as below, which proves compilation and boot stamp are all fine. This is a successful test case using movb $'W' , %al
:
I tried my best searching questions for Linker script, gcc options, inline assembly and real vs virtual machine, but could not fix this problem.
Also it could be problem of how static variables are saved in case of boot-loader which I am yet unaware of.