我正在开发一个用于娱乐和教育的玩具内核(不是课堂项目)。我开始在我的内存管理器上工作,所以我试图INT 0x15, EAX=E820
在仍处于实模式时使用调用从 BIOS 获取内存映射。我正在从 osdev wiki 调整我的功能(这里,在“获取 E820 内存映射”部分)。但是,我希望这是一个可以从我的 C 代码中调用的函数,所以我正在尝试对其进行一些更改。我希望它接受两个参数:一个指向存储映射条目的位置的指针,以及一个指向整数的指针,该整数将按表中的条目数递增。
根据 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 中的调用,那么一切都会如您所愿。
我已经通过谷歌阅读了几乎没有理由ES:DI
直接设置,并且在我发现的代码中,他们将其设置为文字。我应该如何设置ES:DI
,如果我不应该直接设置,我应该如何让 C 和 ASM 以正确的方式交互?