2016-08-19 40 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和變體)早的任何東西上運行。 –

相關問題