web-dev-qa-db-ja.com

Cのブートローダーがコンパイルされない

私はブートローダーを書くのが初めてです。 asmでhelloworldブートローダーを作成し、Cで作成しようとしています。Cでhelloworldブートローダーを作成しましたが、コンパイルできません。

これは私のコードです。何が悪いのですか?なぜコンパイルしないのですか?

void print_char();
int main(void){
char *MSG = "Hello World!";
int i;

__asm__(
    "mov %0, %%SI;"
    :
    :"g"(MSG)
);
for(i=0;i<12;i++){
    __asm__(
        "mov %0, %%AL;"
        :
        :"g"(MSG[i])
    );
    print_char();
}

return 0;
}

void print_char(){
__asm__(
    "mov $0X0E, %AH;"
    "mov $0x00, %BH;"
    "mov $0x04, %BL;"
    "int $0x10"
);
}
21
Dnyanesh Gate

http://wiki.osdev.org/Rolling_Your_Own_Bootloader と、次のブートローダーセクションもご覧になることをお勧めします: http://www.brokenthorn.com/Resources/ OSDevIndex.html

自分でブートローダーを作成するための優れたチュートリアルがあります。さらに情報が必要な場合は、freenodeの#osdevチャネルに参加して、ディスカッションに参加することもできます。

19
phoxis

ここでは多くのことを想定します。x86システムでブートローダーを実行したい場合、* nixボックスにgccツールチェーンを設定します。

ブートローダーを作成する際に考慮すべき点がいくつかあります。

  1. vBRの510バイトの制限。パーティションテーブルにより、MBRの場合はさらに小さくなります(システムに必要な場合)。
  2. リアルモード-16ビットレジスタとseg:オフアドレス指定
  3. ブートローダーは、物理アドレス7c00hで実行するためにリンクする必要があるフラットバイナリである必要があります
  4. 外部の「ライブラリ」参照はありません(そうです!)

ここで、gccにそのようなバイナリを出力させたい場合は、それを使っていくつかのトリックを実行する必要があります。

  1. デフォルトでは、gccは32ビットコードを分割します。リアルモードで実行されるgcc出力コードを作成するには、各Cファイルの先頭に__asm__(".code16gcc\n")を追加します。
  2. gccは、コンパイルされたオブジェクトをELFで出力します。 7c00hで静的にリンクされたビンが必要です。ファイルを作成するlinker.ld以下の内容

    ENTRY(main);
    SECTIONS
    {    
        . = 0x7C00;    
        .text : AT(0x7C00)
        {
            _text = .;
            *(.text);
            _text_end = .;
        }
        .data :
        {
            _data = .;
            *(.bss);
            *(.bss*);
            *(.data);
            *(.rodata*);
            *(COMMON)
            _data_end = .;
        }    
        .sig : AT(0x7DFE)    
        {        
            SHORT(0xaa55);
        }    
        /DISCARD/ :
        {
            *(.note*);
            *(.iplt*);
            *(.igot*);
            *(.rel*);
            *(.comment);
            /* add any unwanted sections spewed out by your version of gcc and flags here */    
        }
    }
    
  3. ブートローダーコードをbootloader.cとブートローダーをビルドします

    $ gcc -c -g -Os -march=i686 -ffreestanding -Wall -Werror -I. -o bootloader.o bootloader.c
    $ ld -static -Tlinker.ld -nostdlib --nmagic -o bootloader.elf bootloader.o
    $ objcopy -O binary bootloader.elf bootloader.bin
    
  4. ASMを使用してブートローダーをすでに構築しているので、残りは明らかだと思います。

-私のブログから取得: http://dc0d32.blogspot.in/2010/06/real-mode-in-c-with-gcc-writing.html

14
dc0d32

ブートローダーはASMで書かれています。

Cコード(またはC++など)をコンパイルすると、コンパイラは人間が読めるコードをマシンコードに「変換」します。そのため、結果について確信が持てません。

PCが起動すると、BIOSは特定のアドレスからコードを実行します。そのコードは、直接実行可能である必要があります。

そのため、Assemblyを使用します。これは、変更されていないコードを作成するための唯一の方法であり、プロセッサによって、記述どおりに実行されます。

Cでコーディングする場合でも、ASMブートローダーをコーディングする必要があります。これは、使用するコンパイラーによって生成されたマシンコードを適切にロードするために担当します。

各コンパイラは異なるマシンコードを生成することを理解する必要があります。実行前に前処理が必要になる場合があります。

BIOSでは、マシンコードを前処理できません。 PCの起動はメモリの場所へのジャンプにすぎません。つまり、この場所にあるマシンコードは直接実行されます。

7
Macmade

GCCを使用しているため、さまざまな「ターゲット環境」に関する情報ページを読む必要があります。あなたはおそらく-ffreestandingフラグを使いたいでしょう。また、コンパイラの醜い魔法を避けるために、-fno-stack-protectorフラグを使用する必要がありました。

次に、memsetなどが見つからないというリンカーエラーが表示されます。したがって、これらの独自のバージョンを実装してリンクする必要があります。

2
rodrigo

私は数年前にこれを試しました-オプションが変更された可能性があります。

gcc-ffreestandingで実行し(リンクしないでください)、フラグ-static-nostdlibldを使用してリンクする必要があります。

1
Foo Bah