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

32位自制内核中相同指令在main与函数内执行结果异常求助

32位自制内核函数调用异常问题

问题现象

开发32位自制内核时,相同的内存写入指令在main函数中执行正常,但在自定义函数foo中执行时行为异常。排查确认是foo内部的指针解引用操作失效,写入0xb8000的是错误数据(表现为清屏,推测是写入了0),预期两者行为一致但实际不符。

相关代码

C代码

int foo(const char *str)
{   
    *(char*)0xb8000 = *str; // 执行后清屏,推测写入了0
}
extern void main() {
    const char str[4] = {'A', 'B', 'C', '\0'};
     *(char*)0xb8000 = *str; // 执行正常,写入'A'
    for(int i=0;i<1000000000;i++); // 延时
    foo(str);
    for(;;);
    return;
}

启动代码(boot.asm)

[org 0x7c00]
KERNEL_LOCATION equ 0x1000

mov [boot_disk], dl

; 设置栈
xor ax, ax                          
mov es, ax
mov ds, ax
mov bp, 0x8000
mov sp, bp


; GDT加载等操作


[bits 32]
start_protected_mode:
    mov ax, DATA_SEG
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    
    mov ebp, 0x90000        ; 32位栈基址
    mov esp, ebp

    jmp KERNEL_LOCATION


times 510-($-$$) db 0
dw 0xaa55

Makefile

all:
	x86_64-elf-gcc -Wall -nostdlib -ffreestanding -m64 -g -c "kernel.c" -o "kernel.o"
	x86_64-elf-gcc -Wall -nostdlib -ffreestanding -m64 -g -c "idt.c" -o "idt.o"
	x86_64-elf-gcc -Wall -nostdlib -ffreestanding -m64 -g -c "system.c" -o "system.o"
	nasm "kernel_enrty.asm" -f elf64 -o "kernel_entry.o"
	nasm "start.asm" -f elf64 -o "start.o"
	x86_64-elf-ld -nostdlib -o "full_kernel.bin" -Ttext 0x1000 "kernel_entry.o" "start.o" "idt.o" "system.o"  "kernel.o" -j .text --oformat binary
	nasm "boot.asm" -f bin -o "boot.bin"
	cat "boot.bin" "full_kernel.bin" > "everything.bin"
	nasm "padding.asm" -f bin -o "padding.bin"
	cat "everything.bin" "padding.bin" > "OS.bin"

问题根源

核心矛盾是编译目标架构不匹配:

  • 内核运行在32位保护模式下,但Makefile中使用-m64参数编译64位代码,同时nasm生成elf64格式的目标文件。
  • 64位系统的函数调用约定(System V AMD64)使用寄存器(如rdi)传递第一个参数,而32位系统通常使用栈传参。在32位模式下执行64位编译的foo函数时,函数无法正确获取str参数,导致*str读取到错误值(大概率是0),写入0xb8000后出现清屏现象。

解决方案

修改编译和链接流程,统一为32位目标架构:

  1. 修改GCC编译参数:将所有-m64替换为-m32,编译32位代码:
    x86_64-elf-gcc -Wall -nostdlib -ffreestanding -m32 -g -c "kernel.c" -o "kernel.o"
    
  2. 修改NASM编译参数:将-f elf64替换为-f elf32,生成32位ELF目标文件:
    nasm "kernel_enrty.asm" -f elf32 -o "kernel_entry.o"
    
  3. 修改链接器参数:添加-m elf_i386参数,指定链接32位目标文件:
    x86_64-elf-ld -m elf_i386 -nostdlib -o "full_kernel.bin" -Ttext 0x1000 "kernel_entry.o" "start.o" "idt.o" "system.o"  "kernel.o" -j .text --oformat binary
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 09:05:54