我正在尝试为我的 C 内核编写一个基本的页面管理器。代码是这样的:
#define NUM_PAGES 1024
#define PAGE_SIZE 4096
#define NULL 0
#define IMPORTANT_SEGMENT 0xC0900000
struct page {
void * addr;
int in_use;
};
struct page CORE_FILE[NUM_PAGES];
void mem_init() {
for (int i = 0; i < NUM_PAGES; i++) {
CORE_FILE[i].addr = (void*)IMPORTANT_SEGMENT+PAGE_SIZE*i;
CORE_FILE[i].in_use = 0;
}
}
void * allocate() {
for (int i = 0; i < NUM_PAGES; i++) {
if (!CORE_FILE[i].in_use) {
CORE_FILE[i].in_use = 1;
return CORE_FILE[i].addr;
}
}
return NULL;
}
int deallocate(void* p) {
for (int i = 0; i < NUM_PAGES; i++) {
if (CORE_FILE[i].addr == p && CORE_FILE[i].in_use) {
CORE_FILE[i].in_use = 0;
return 0;
}
}
return -1;
}
CORE_FILE 是一组结构,仅包含一个字段(用于指示页面是否正在使用)和一个地址(我使用从 IMPORTANT_SEGMENT = 0xC0900000 开始增长的连续地址)。
当我调用 allocate()
时,它会返回正确的 void*
,例如我将其转换为 char,但是当我写入地址时,它什么也不做。
我已经检查了 GDB 指向的地址并且是正确的地址。 但是当我检查它的内容时,它们还没有更新(仍然是 0)。
void kmain(void) {
mem_init();
int * addr = (int*)allocate();
*addr = 5;
}
我给 qemu 4 GB 的 RAM 执行:
qemu-system-i386 -m 4G -kernel kernel -gdb tcp::5022
也许我正在写入不存在的内存,或者我可能正在覆盖之后的地址内容。我不知道。
任何想法将不胜感激。
提前谢谢你。
[编辑] 这是我使用的引导加载程序:
bits 32
section .text
;multiboot spec
align 4
dd 0x1BADB002 ;magic
dd 0x00 ;flags
dd - (0x1BADB002 + 0x00) ;checksum. m+f+c should be zero
global start
global keyboard_handler
global read_port
global write_port
global load_idt
extern kmain ;this is defined in the c file
extern keyboard_handler_main
read_port:
mov edx, [esp + 4]
;al is the lower 8 bits of eax
in al, dx ;dx is the lower 16 bits of edx
ret
write_port:
mov edx, [esp + 4]
mov al, [esp + 4 + 4]
out dx, al
ret
load_idt:
mov edx, [esp + 4]
lidt [edx]
sti ;turn on interrupts
ret
keyboard_handler:
call keyboard_handler_main
iretd
start:
cli ;block interrupts
mov esp, stack_space
call kmain
hlt ;halt the CPU
section .bss
resb 8192; 8KB for stack
stack_space:
我的链接.ld
OUTPUT_FORMAT(elf32-i386)
ENTRY(start)
SECTIONS
{
. = 0x100000;
.text : { *(.text) }
. = 0x200000;
.data : { *(.data) }
. = 0x300000;
.bss : { *(.bss) }
}
Edit2:我用这个编译
nasm -f elf32 kernel.asm -o kasm.o
gcc -g -fno-stack-protector -fno-builtin -m32 -c memory.c -o memory.o
gcc -g -fno-stack-protector -fno-builtin -m32 -c kernel.c -o kc.o
ld -m elf_i386 -T link.ld -o kernel kasm.o memory.o kc.o
最佳答案
问题在于保护模式和实模式,当计算机以 16 位实模式启动时,这使您能够处理 1 MB 的数据。上面的所有内容都不适合读/写。如果我将 IMPORTANT_SEGMENT 更改为 0x300000,它会起作用。
现在我必须创建并加载我的 gdt,启用 a20 行,启用保护模式,设置寄存器并跳转到我的代码。
关于C 写入绝对地址不更新值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56307186/