我正在開發玩具內核以獲得樂趣和教育(不是類項目)。我開始在內存管理器上工作,所以我試圖在仍處於實模式時使用INT 0x15, EAX=E820
調用從BIOS獲取內存映射。我正在從osdev wiki(here,在「獲取E820存儲器映射」一節)中調整我的功能。然而,我希望這是一個我可以從我的C代碼調用的函數,所以我試圖改變它一點。我希望它有兩個參數:一個指向存儲映射條目的位置的指針,以及一個指向整數的指針,該整數將根據表中的條目數增加。內核開發:設置ES:實模式中的DI
根據wiki,ES:DI
需要指向數據存儲位置,因此我將第一個參數分爲兩部分(段選擇器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以正確的方式進行交互?
呃? ES:DI是幾個彙編指令的目標地址。爲什麼設置ES或DI會出現問題? –
我不確定,但虛擬機崩潰在這些MOV命令,所以我認爲問題在那裏。我對彙編代碼很陌生,所以我也可能犯了一個愚蠢的錯誤。我的猜測是,它的大小與我試圖設置的數據大小有關,但將演員製作成簡短形式並沒有做任何事情,只是產生了一些編譯器警告。可以將它們放在一起嗎? – zrneely
很難判斷你卡在哪裏。最好的資源之一是[** AOA - 目錄**](https://courses.engr.illinois.edu/ece390/books/artofasm/artofasm.html)。特別看第4章。至於使用'segment:[register]'尋址的具體示例,請參閱[** AOA - 15.3.2 - 索引示例**](https://courses.engr.illinois.edu/ece390/books /artofasm/CH15/CH15-4.html#HEADING4-153)如果你在一個64位的盒子上,函數參數不會在棧上傳遞,它們在'RDI,RSI,RDX,RCX,R8和R9 ' –