3

OSのような古い16ビットDOSを構築しようとしています。

私のカーネルコードの例:

    asm(".code16\n");
    void putchar(char);
    int main()
    {
    putchar('A');
    return 0;
    }
    void putchar(char val)
    {
       asm("movb %0, %%al\n"  
           "movb $0x0E, %%ah\n" 
           "int $0x10\n"
          :
          :"r"(val)
          ) ;
    }

これは私がそれをコンパイルする方法です:

nasm -f bin -o ./bin/boot.bin ./source/boot.asm
gcc -nostdinc -fno-builtin -I./include -c -o ./bin/kernel.o ./source/kernel.c
ld -Ttext=0x9000 -o ./bin/kernel.bin ./bin/kernel.o -e 0x0
dd if=/dev/zero of=./bin/empty.bin bs=1440K count=1
cat ./bin/boot.bin ./bin/kernel.bin ./bin/empty.bin|head -c 1440K > ./bin/os
rm ./bin/empty.bin

仮想マシンで実行します。

定数値の putchar 関数 (カーネル コード内) を作成すると、次のようになります。

 void putchar()
 {
    char val = 'A';
    asm("movb %0, %%al\n" 
    "movb $0x0E, %%ah\n" 
    "int $0x10\n"
    :
    :"r"(val)
    ) ;
 }

その後、正常に動作します。しかし、引数を渡すと (前のコードにあります)、任意の文字にスペースが出力されます。私は何をすべきか?

4

2 に答える 2

3

gcc に 16 ビット コードを生成させようとしている場合は、関数パラメーターのスタック操作を正しく行うために、.code16gccではなくを使用する必要があります。ガスのドキュメントの「16 ビット コードの記述」を参照してください。.code16

(また、使用している gcc のバージョンによっては、コンパイルされたコードの前にアセンブラーが実際にディレクティブに遭遇するようにするためにkernel.c-fno-unit-at-a-timeまたは-fno-toplevel-reorderオプションを使用してコンパイルする必要がある場合があります。そうしないと、コンパイラーがシャッフルする可能性があります。)asm()

于 2010-04-26T23:23:48.737 に答える
1

問題を解決する別のコンパイラを見つけました: bcc

これは、8086 CPU 用の C コンパイラであり、ブート ローダーや BIOS 関連の 8086 コードの開発に重要です。

于 2011-11-29T12:57:23.290 に答える