0

私は 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 とセグメント セレクターの概念全体に不慣れです........そして、現時点ではページングまたはマルチタスクを有効にすることはできません.理由を説明したくありません....

4

1 に答える 1

0

まず、、だけdsでなく、も設定する必要がesありssます。そうしないと、一部の命令はds.baseセグメントベース(eg mov eax, [ebx])として使用されますが、他の命令はss.base(eg mov eax, [ebp+8])またはes.base(eg rep movsd)を使用し、それらは異なるため、アドレス指定に一貫性がなくなります。

あなたが抱えている可能性のある別の問題は間違っていますcs(無効な命令例外はそれを示しています)。x86コードは、一般的に位置に依存しません。データセクションがメモリにロードされる場所とメモリ内にあるはずの場所の違いを補正するために別のデータセグメントを作成して使用する必要があるのと同じように(さまざまなELFヘッダー/セクションがそれを示します)、コードセクションでも同じことをする必要があります。csファーコール、ファージャンプ、ファーリターンのいずれかを使用して変更できます。

于 2013-01-15T09:56:40.730 に答える