私は楽しみと教育のためのおもちゃのカーネルに取り組んでいます (クラスのプロジェクトではありません)。INT 0x15, EAX=E820
メモリ マネージャの作業を開始しているので、リアル モードのまま呼び出しを使用して BIOS からメモリ マップを取得しようとしています。私はosdev wikiから自分の機能を適応させています(ここでは、「E820メモリマップの取得」セクションにあります)。ただし、これを C コードから呼び出すことができる関数にしたいので、少し変更しようとしています。マップ エントリを格納する場所へのポインタと、テーブル内のエントリの数だけインクリメントされる整数へのポインタです。
ウィキによると、ES:DI
はデータを保存する場所を指す必要があるため、最初の引数を 2 つ (セグメント セレクターpointer_to_map / 16
とオフセットpointer_to_map % 16
) に分割しました。C コードの一部を次に示します。
typedef struct SMAP_entry {
unsigned int baseL; // Base address, a QWORD
unsigned int baseH;
unsigned int lengthL; // Length, a QWORD
unsigned int lengthH;
unsigned int type; // entry type
unsigned int ACPI; // extra data from ACPI 3.0
} SMAP_entry_t;
SMAP_entry_t data[100];
kprint("Pointer: ");
kprint_int((int) data, 16);
kprint_newline();
int res = 0;
read_mem_map(((int) data) / 16, ((int) data) % 16, &res);
kprint("res: ");
kprint_int(res, 16);
kprint_newline();
これが私の ASM コードの一部です。
; performs a INT 0x15, eax=0xE820 call to find the memory map
; inputs: the pointer to the data table / 16, the pointer % 16, a pointer to an dword (int) which will be
; incremented by the number of entries after this function returns.
; preserves: no registers except esi
read_mem_map:
mov es, [esp + 4] ; set es to the value of the first argument
mov di, [esp + 8] ; set di to the value of the second argument
プログラムがトリプル フォールトを起こし、そこで VM をシャットダウンするため、ここに貼り付けているのはそれだけです。コマンドを移動するret
と、最初の行で関数がクラッシュすることがわかりました。C で呼び出しをコメントアウトすると、すべてが期待どおりに機能します。
直接設定する理由はほとんどないことをGoogleで読んだことがありES:DI
ます。私が見つけたコードでは、それをリテラルに設定しています。どのように設定ES:DI
すればよいですか? また、直接設定しない場合は、C と ASM が正しく対話するようにするにはどうすればよいですか?