You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

内核位于0x1000时,如何用C与汇编获取内存数据?

保护模式下C内核物理内存映射解决方案

一、流程结构调整(彻底规避内存覆盖)

重新规划各阶段内存布局,消除冲突:

  • MBR(0x7C00):仅负责加载ASM内核到0x10000(16KB位置,远离0x0600、0x1000等敏感区域),执行完成后直接跳转至ASM内核入口
  • ASM内核(0x10000):按顺序完成3项核心操作:
    1. 在实模式下读取E820内存映射,存储到0x20000(32KB位置,与所有加载区无重叠)
    2. 加载C内核到原有地址0x1000(保留现有配置,避免崩溃)
    3. 切换到保护模式,传递内存映射的起始地址和条目数给C内核,再调用C内核入口
  • C内核(0x1000):接收内存映射参数后,执行IDT加载、ISR安装等原有逻辑,再基于映射初始化物理内存管理器

二、E820内存映射汇编实现(无覆盖风险)

以下是实模式下可靠读取E820映射的汇编代码,直接嵌入ASM内核的实模式段:

; 读取E820内存映射,存储到0x20000
; 返回参数:ecx=条目数,edi=映射起始地址(0x20000)
e820_read:
    xor ebx, ebx                ; ebx初始化为0,标记首次调用
    mov edx, 0x534D4150         ; "SMAP" magic值,必须传递给int 0x15
    mov edi, 0x20000            ; 映射存储起始地址,远离所有加载区
    xor ecx, ecx                ; 条目计数初始为0

e820_loop:
    mov eax, 0xE820             ; E820功能号
    mov ecx, 24                 ; 每个条目的标准大小(24字节)
    int 0x15                    ; 调用BIOS中断获取映射条目
    jc e820_done                ; 进位标志置位表示出错,退出循环
    cmp eax, 0x534D4150         ; 检查返回的magic值是否合法
    jne e820_done
    add edi, 24                 ; 移动指针到下一个条目存储位置
    inc ecx                     ; 条目数+1
    test ebx, ebx               ; ebx为0表示无更多条目
    jne e820_loop

e820_done:
    ; 切换保护模式前,将ecx(条目数)和0x20000(映射地址)存入寄存器传递给C内核
    mov ebx, ecx                ; ebx暂存条目数
    mov ecx, 0x20000            ; ecx暂存映射起始地址

三、C内核对接实现

  1. 定义与汇编匹配的E820条目结构体:
#include <stdint.h>

typedef struct {
    uint64_t base_addr;  // 内存区域起始物理地址
    uint64_t length;     // 内存区域长度
    uint32_t type;       // 类型:1=可用,2=保留,3=ACPI回收区等
    uint32_t acpi_ext;   // ACPI扩展字段(可忽略)
} e820_entry_t;
  1. 定义C内核入口函数,接收汇编传递的参数:
// 用cdecl调用约定匹配汇编传参规则
void __attribute__((cdecl)) kernel_main(uint32_t e820_count, e820_entry_t *e820_map) {
    // 执行原有逻辑:加载IDT、安装ISR、设置PIT和键盘
    // ...
    
    // 基于e820_map初始化物理内存管理器
    for (uint32_t i = 0; i < e820_count; i++) {
        if (e820_map[i].type == 1) {
            // 标记该区域为可用物理内存
            // ...
        }
    }
    
    // 后续逻辑
    while (1);
}

四、关键避坑点

  • 绝对禁止在0x0600、0x1000、0x7C00区域存储持久数据,这些区域会被BIOS或内核加载过程覆盖
  • E820内存映射必须在实模式下读取,切换到保护模式后无法再调用BIOS中断
  • 分页功能需在C内核完成内存映射解析和物理内存管理器初始化后再启用,过早启用会导致地址映射混乱

内容的提问来源于stack exchange,提问作者Tech

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 12:15:37