これは答えるのがかなり難しい質問だと思います。主な理由は、間違っている可能性のあるものが非常に多く、特定するのが難しいためです。しかし、私はできるだけ多くの情報を提供します。うまくいけば、それが役立つでしょう。
私はD言語とDigitalMarsDコンパイラを使用して独自のカーネルを書き始め、再配置可能なフラットバイナリを生成する方法を見つけるのに多くの問題を抱えた後、最終的に通常のPEファイルを生成するというアイデアを思いつきました。アドレス、およびそのすべてのヘッダーをバイト(NOPオペコード)0xC0000000
に置き換えます。0x90
これは完全にうまく機能し、16ビットアセンブリベースのブートローダーの助けを借りて、画面に物事を書き込んだり、ページングを設定したり、プロテクトモードに入るなどを完全にうまく行うことができました。
すべてが順調でした。つまり、カーネルで使用するためにDランタイムライブラリを移植することにしました。ライブラリのサブセットを抽出し、それを変更してアプリにコンパイルできるようにしました。次に、プログラムを実行しました。(注:ライブラリをまったく使用しませんでし た。私のコードは、起動後に実行される最初のコードでした。最初に発生したのは画面への印刷であり、その前にランタイムコードは呼び出されませんでした。)"Kernel"
AD配列(したがって、文字列は単なるaであるため、文字列char[]
)は、ポインタとサイズメンバーを持つ構造体にすぎないため、32ビットシステムでは8バイトの大きさになります。面白いことに、プログラムを実行すると、構造体のメンバーがゼロであることがわかりました。つまり、ポインターとサイズの両方がゼロでした。(ポインターの値と長さのメンバーを画面に出力することでこれを確認しました。どちらもゼロでした。)ランタイムのソースコードを削除するとすぐに(とにかく実行されませんでした)、正常に機能しました。 。
これを2つの可能性に絞り込みました。
スタックが正しく設定されていませんでした。ランタイムライブラリがなくてもすべてが正常に機能するため、これを除外し、ファイルを逆アセンブルして、コードの前に他のコードが実行されていないことを確認しました。
PEファイルセクションに何かおかしいことがあります。実行時のバージョンに2つのTLS(スレッドローカル)変数があることを確認しました。案の定、(スレッドローカルではなく)共有させたところ、コードは機能しました!ただし、別のファイルで記述したコードを呼び出したときに、コードで同じ問題が発生しました
kernel.d
。スタートアップファイルである、のみが文字列で正しく動作しました。他のファイルでは、配列は再びゼロになりました。
さて、なぜこれが起こっているのかについて誰かが推測していますか?
さらに情報が必要な場合は、喜んで投稿します。
ありがとうございました!