4

私はリアルモードのOSに取り組んでおり、アセンブリで書き込み、NASMを使用してフラットな.bin実行可能ファイルにコンパイルしています。
OSの一部をCで記述したいので、文字列にアクセスして最初の文字を出力する実験プログラム(ctest.c)を記述しました。

void test();

int main() { test(); return 0; }

char msg [] = "Hello World!";

void test() {
    _asm
    {
        mov si, word ptr [msg]
        mov al, [si]
        mov ah, 0eh
        int 10h
    }
    for(;;);
}

を使用してOpenWatcomv1.9でこれをコンパイルしまし wcl ctest.c -lr -l=COM た。これにより、ctest.comが作成されます。NASMアセンブリで記述したカーネルは、このプログラムを0x2010:0x0000にロードし、DSとESを0x2000:0x0000に設定してから、0x2010:0x0000にジャンプします。これが、アセンブリで記述され、。でコンパイルされた.COMプログラムを呼び出す方法ですnasm -f bin test.asm -o test.com
OSを(Bochsを使用して)テストすると、ctest.comが正常に読み込まれますが、msg[]の一部ではない意味のない文字が出力されます。
誰かがこれについて何か提案がありますか?文字列が間違った場所で初期化されているだけだと思います。これを16ビットOSとして残しておきたいです。
ありがとう!

4

2 に答える 2

4

間違ったアドレスを使用しています。

0x2000:0x0100でロードして0x2000:0x0100にジャンプする(その前にDS = ES = SS=0x2000とSP=0を設定することを忘れないでください)か、0x2000:0x0000でロードします(0x2000 *のため0x1FF0:0x0100と同等 0x10 + 0x0000 = 0x1FF0 * 0x10 + 0x0100 = 0x20000 =リアルモードの物理メモリアドレス)そして0x1FF0:0x0100にジャンプします(その前にDS = ES = SS=0x1FF0とSP=0を設定することを忘れないでください)。

このすべての理由は、コンパイルされたx86コードは一般に位置に依存せず、移動する場合は、コード内のデータオフセットを調整する必要があるためです。明らかに、あなたはこれらの調整をしていませんでした。単純なケースでは、調整するものがなく、間違ったアドレスで逃げました。

編集

実際、ここにはもっと多くの問題があります:

  1. mov si, word ptr [msg]lea si, byte ptr [msg]文字列の中にあるものをロードしたくないので、に変更する必要がありsiます。文字列のアドレスをロードしたいのです。
  2. OWによってプログラムにリンクされているスタートアップコードはDOSに依存しており、プログラムを起動するときに持っていないDOS関数を呼び出します。これを回避する方法については、こちらをご覧ください。
于 2012-03-24T20:56:20.703 に答える
1

MS-DOSでは、COMプログラムはオフセット0x100でロードされました。OpenWatcomがその仮定をしていると思います。COMプログラムを0x2010:0x0100にロードして、それが何をするかを確認することをお勧めします。

于 2012-03-24T19:58:25.863 に答える