2016-08-19 62 views
0

我写一个简单的x86引导程序。为什么这个引导程序将只打印“S”

这是即时通讯时遇到问题的C程序: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); 

} 

当我尝试打印的主要功能中的字符串,它的工作原理。但是当我将字符串传递给另一个执行相同指令的函数时,仍然只能将S打印到屏幕上。所以最终的输出看起来是这样的:

Hello World 
S 

这里是我使用的连接文件:test.ld

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

下面是我用来编译C程序,将其链接

的命令
$ 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 

我用bochs仿真器来测试这个引导程序

+0

一个独立的程序必须设置堆栈和段寄存器。 – stark

+0

查看duskwuffs评论不使用GCC的16位代码。 OpenWatcom是针对16位代码恕我直言的_C_编译器的最佳选择。但是,如果你知道自己在做什么,请了解GCC生成的代码的细微差别(及其局限性),你可以看看这样的代码[代码示例](http://www.capp-sysware.com/misc/ ircasm/gccboot /)。这非常适合使用引导加载程序的BIOS中断进行打印。 –

+1

差不多[帮助建设一个16位操作系统]完全相同的副本(http://stackoverflow.com/questions/2713340/help-in-building-an-16-bit-os) –

回答

4

你不能用GCC做到这一点。忽略所有可以说你可以的教程 - 他们错了。

请注意最重要的是GCC不是16位编译器__asm__(".code16\n")指令并没有把它变成一个;它只是将汇编程序混淆成将GCC的输出从32位x86重定向到16位。这会导致奇怪的和意外的行为,特别是在任何使用指针的代码中。

如果你想要写一个x86引导装载程序,你将需要:

  • 使用C编译器,可以专门针对16位x86(“实模式”)。例如,考虑OpenWatcom工具链。

  • 成为熟悉x86实模式的怪癖 - 特别是细分。

  • 写在组件中的引导程序,特别是启动代码的一些部分。

+0

'这样的东西来设置一个无限循环我还建议如果你使用OpenWatcom以16位代码为目标,您正在考虑从引导加载程序执行此操作 - [JLOC](http://geezer.osdevbrasil.net/johnfine/jloc.htm)链接器是天赐良机。不幸的是,它是一个没有源代码的DOS程序,但可以在Linux上的DOSEMU等模拟器上运行。 –

+1

我不推荐使用GCC作为16位代码的原因。然而,事实上它是可行的,但前提是你对发生的事情有了很好的理解。如果整个程序可以在内存的第一个64k中加载到内存中,并且CS = DS = ES = SS = 0,那么指针的所有问题都会结束。当然,没有任何由GCC的'.code16'指令生成的代码可以在比386处理器(8086/80186/80286和变体)早的任何东西上运行。 –