私は 32 ビット OS を開発しており、問題なく動作する ELF ローダーを開発しました。現在、ページングを有効にしておらず (後で有効にする予定ですが、現在はカーネル モジュールをロードしようとしています)、起動時にモジュールを実行しようとしています。基本的に、現時点ではマルチタスクが完全に実装されていないため、各モジュールをロードし、init を呼び出して (割り込みハンドラーをインストールし、モジュールの目的を設定するだけです)、終了して次のモジュールを実行します。動作しますが、C プログラムのポインターを使用して何もできません (カーネル データ セグメントを使用していると考えているため)。したがって、基本的に私がやりたいことは、RAM のモジュール .data セグメントを指す新しいデータ セグメントを作成することです。GDTのようにエントリ番号6を設定することでこれを行っています。
setGDTEntry(6, DataAddress,DataSize, 0xF2, 0xCF);
setEntry メソッドは問題なく動作します。次のようになります。
void setGDTEntry(int num, uint Base, uint limit, byte access, byte gran)
ここでも両方とも 100% 動作します。データ セグメント セレクターを変更すると、問題が発生します。私はアセンブリでこれを行っています.ELFのエントリポイントはEAXに保存されています.
mov ax, 30h ; This is 8 * 6, the GDT entry containing the new data segment
mov ds, ax ; set data segment
call address ; JUMP!!!!
mov ax, 0x10 ; Restore kernel data segment
mov ds, ax ; set data segment
これにより、カーネルがパニックになり、CPU 例外 0x6、無効なオペコードが発生します。私の C プログラムのソース コードは、テキストをビデオ RAM にコピーする単なる hello world プログラムです (特に注目すべき点はありません)。私が間違っていることを誰かが知っていますか?私は GDT とセグメント セレクターの概念全体に不慣れです........そして、現時点ではページングまたはマルチタスクを有効にすることはできません.理由を説明したくありません....