编写一个简单的Bootloader HelloWorld – 错误函数打印字符串

我尝试创建一个打印“hello world”的简单引导程序。

当我调用一个只打印“hello world”的函数时,我可以这样做,但是当我调用一个函数来打印一个特定的字符串时,什么也没发生。

为此,我使用两个文件。 第一个是boot.ld,第二个是boot.cpp(它也可以在C中使用boot.c)。

首先,我从终端创建软盘:

dd if = / dev / zero of = floppy.img bs = 512 count = 2880

其次,我编译代码(boot.cpp和boot.ld):

gcc -c -g -Os -m64 -ffreestanding -Wall -Werror boot.cpp -o boot.o

ld -static -Tboot.ld -nostdlib –nmagic -o boot.elf boot.o

objcopy -O binary boot.elf boot.bin

最后,我将boot.bin添加到floppy.img中:

dd if = boot.bin of = floppy.img

现在我们只需要从VirtualBox的存储面板添加软盘并启动我们的虚拟机。

FloppyImage

源代码

来自: http : //www.codeproject.com/Articles/664165/Writing-a-boot-loader-in-Assembly-and-C-Part

boot.ld

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

boot.cpp(或boot.c)

 void cout(); void main() { cout(); } void cout() { __asm__ __volatile__("movb $'h' , %al\n"); __asm__ __volatile__("movb $0x0e, %ah\n"); __asm__ __volatile__("int $0x10\n"); __asm__ __volatile__("movb $'e' , %al\n"); __asm__ __volatile__("movb $0x0e, %ah\n"); __asm__ __volatile__("int $0x10\n"); __asm__ __volatile__("movb $'l' , %al\n"); __asm__ __volatile__("movb $0x0e, %ah\n"); __asm__ __volatile__("int $0x10\n"); __asm__ __volatile__("movb $'l' , %al\n"); __asm__ __volatile__("movb $0x0e, %ah\n"); __asm__ __volatile__("int $0x10\n"); __asm__ __volatile__("movb $'o' , %al\n"); __asm__ __volatile__("movb $0x0e, %ah\n"); __asm__ __volatile__("int $0x10\n"); __asm__ __volatile__("movb $' ' , %al\n"); __asm__ __volatile__("movb $0x0e, %ah\n"); __asm__ __volatile__("int $0x10\n"); __asm__ __volatile__("movb $'w' , %al\n"); __asm__ __volatile__("movb $0x0e, %ah\n"); __asm__ __volatile__("int $0x10\n"); __asm__ __volatile__("movb $'o' , %al\n"); __asm__ __volatile__("movb $0x0e, %ah\n"); __asm__ __volatile__("int $0x10\n"); __asm__ __volatile__("movb $'r' , %al\n"); __asm__ __volatile__("movb $0x0e, %ah\n"); __asm__ __volatile__("int $0x10\n"); __asm__ __volatile__("movb $'l' , %al\n"); __asm__ __volatile__("movb $0x0e, %ah\n"); __asm__ __volatile__("int $0x10\n"); __asm__ __volatile__("movb $'d' , %al\n"); __asm__ __volatile__("movb $0x0e, %ah\n"); __asm__ __volatile__("int $0x10\n"); } 

输出:

TestBootLoader1

漏洞的源代码

boot.cpp(或boot.c)

 void cout(const char* str); void main() { cout("hello world"); } void cout(const char* str) { while(*str) { __asm__ __volatile__ ("int $0x10" : : "a"(0x0e00 | *str), "b"(0x0007)); ++str; } } 

输出:

TestBootLoader2

为什么输出是空的?

我的function有什么问题?

我忘了什么?

谢谢你的帮助。

在我的交叉编译器( i686-elf-gcc (GCC) 4.9.2 )上,后面的代码生成以下(dis)程序集:

  boot.o: file format elf32-i386 Disassembly of section .text: 00000000 : 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 53 push %ebx 4: bb 07 00 00 00 mov $0x7,%ebx 9: 8b 55 08 mov 0x8(%ebp),%edx c: 0f be 02 movsbl (%edx),%eax f: 84 c0 test %al,%al 11: 74 08 je 1b  13: 80 cc 0e or $0xe,%ah 16: cd 10 int $0x10 18: 42 inc %edx 19: eb f1 jmp c  1b: 5b pop %ebx 1c: 5d pop %ebp 1d: c3 ret 

我是否对使用GCC(非16位兼容编译器)和16位内容(BIOS中断)非常感兴趣。 如果您要执行16位代码,请在完全组装中执行此操作! GCC会搞砸它,因为它生成的32位代码将在16位模式下运行 。 如果你想直接使用C / C ++,那么你想要编写的内容可能不是引导加载程序,而是内核 。 在这种(普通)案例中,阅读无可争议的神圣仪式,以启动您进入OSDev 。 你的第一个例子运作的事实只是运气,任何微小的变化都可能打破一切,甚至导致神话恐怖的三重错误,内核恐慌本身的噩梦 。

无论如何,你最好直接写入VGA DMA内存而不是使用BIOS调用(首先需要进入保护模式 ,然后设置VGA硬件和模式 (GRUB为你做这个,但是你要创建一个bootloader,不是你呢?)):

 void PrintString(const char *str) { uint16_t *vga = (uint16_t*)0xB8000; for(; *str != '\0'; str++, vga++) *vga = ((uint16_t)0x07 << 8) | *str; // Light grey on a black background, nice! } 

顺便说一句 ,你可能会发现OSDev社区,wiki和论坛非常有用。 并且,如评论中所示,您应该使用.code16作为真实模式代码,并且您的链接文章已经显示其年龄。

感谢@ MichaelPetch的回答。

源代码:

boot.ld

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

boot.cpp

也在这里: http : //pastebin.com/6NV3UMjE

 asm(".code16gcc"); __asm__("jmpl $0x0000, $main\n"); void cout(const char* str); void main() { __asm__ __volatile__ ("xor %ax, %ax\n"); __asm__ __volatile__ ("mov %ax, %ds\n"); cout("Hello World"); __asm__ __volatile__("cli\n"); __asm__ __volatile__("hlt\n"); } void cout(const char* str) { while(*str) { __asm__ __volatile__("int $0x10" : : "a"(0x0e00 | *str), "b"(0x0007)); ++str; } } 

编译:

gcc -c -g -O0 -m32 -ffreestanding -Wall -Werror boot.cpp -o boot.o

ld -melf_i386 -static -Tboot.ld -nostdlib –nmagic -o boot.elf boot.o

objcopy -O binary boot.elf boot.bin

dd if = boot.bin of = floppy.img conv = notrunc

输出:

产量