c - C 写入绝对地址不会更新值
问题描述
我正在尝试为我的 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# - 在 C# 中预览 PDF
- flask - Flask 在正斜杠后提供具有不同路径的静态文件
- jekyll - 在没有插件的情况下以编程方式触发 jekyll 构建错误?
- sql-server - 使用外键更新基于另一个表的列
- c++ - 程序是可执行的,但是在运行时它会跳过限定值并跳转到最高
- python - 在 python 中使用 split 函数或正则表达式删除其他两个符号之间的字符串
- php - 电报 sendPhoto 方法不刷新
- r - 我在我的 RStudio 中看不到控制台。实际上,我对此无能为力。可能是什么问题?
- ksqldb - 无法使用 KSQL 表访问 kafka 数据
- c - 为什么我们在评估 arr[arr[i]] 的值时要为 arr[i] 分配一个新值?