x86_64汇编:从Bootloader跳转到内核的实操示例求助
16位汇编实现文本模式OS:Bootloader加载内核实操示例
原需求
仅使用汇编语言实现文本模式操作系统,已完成基础16位Bootloader,需实操示例实现内核启动。
现有Bootloader代码
boot.asm
BITS 16 ORG 0x7C00 ; 设置文本视频模式 mov ax, 0x3 int 0x10 ; 设置光标到(0,0)位置 mov ah, 0x02 xor dl, dl xor dh, dh int 0x10 ; 指向文本模式显存段 mov ax, 0xb800 mov es, ax ; 输出初始化信息 mov ah, 0x02 ; 前景绿,背景黑 mov si, msg_1 xor di, di ; di寄存器置0 loop: lodsb ; 从si指向的内存加载字节到al,si自增 or al, al ; 判断是否为字符串结束符(0) jz continue ; 是0则跳转到continue stosw ; 将ax(al字符+ah属性)写入显存 jmp loop continue: ; 设置光标到第37列 mov ah, 0x02 mov dl, 37 int 0x10 finish: cli ; 关闭中断 hlt ; 暂停CPU msg_1: db "操作系统加载成功!", 0 times 510 - ($ - $$) db 0 dw 0xAA55
Makefile
compile: nasm boot.asm -o boot.bin run: qemu-system-x86_64 boot.bin
内核启动实操步骤
1. 编写简单内核代码(kernel.asm)
这个内核保持16位模式,在显存输出内核运行的提示信息:
BITS 16 ORG 0x1000 ; 内核加载到内存0x1000处 start: ; 指向显存段 mov ax, 0xb800 mov es, ax ; 设置属性:前景白,背景蓝 mov ah, 0x1F mov si, msg_kernel ; 光标位置对应显存偏移:第2行第0列,每行80字符,每个字符占2字节,偏移为80*2*2=320 mov di, 320 kernel_loop: lodsb or al, al jz kernel_halt stosw jmp kernel_loop kernel_halt: cli hlt msg_kernel: db "内核已成功启动并运行!", 0
2. 修改Bootloader添加内核加载逻辑
修改boot.asm,在continue标签后添加磁盘读取内核的代码,使用BIOS中断int 0x13读取内核到内存0x1000处,然后跳转到内核执行:
; 原continue部分之后添加: ; 加载内核到内存0x1000 mov ah, 0x02 ; BIOS磁盘读取功能号 mov al, 1 ; 读取1个扇区 mov ch, 0 ; 柱面0 mov cl, 2 ; 扇区2(Bootloader在扇区1) mov dh, 0 ; 磁头0 mov dl, 0 ; 驱动器0(软盘/虚拟磁盘) mov bx, 0x1000 ; 加载到内存段地址0x1000 mov es, bx xor bx, bx ; es:bx = 0x1000:0 = 物理地址0x1000 int 0x13 ; 调用磁盘读取中断 ; 跳转到内核执行 jmp 0x1000:0 ; 远跳转到内核的入口地址 ; 原finish部分保留 finish: cli hlt
3. 修改Makefile编译并生成完整镜像
更新Makefile,添加内核编译步骤,将Bootloader和内核合并成一个可引导镜像:
compile: nasm boot.asm -o boot.bin nasm kernel.asm -o kernel.bin cat boot.bin kernel.bin > os_image.bin run: qemu-system-x86_64 os_image.bin
4. 测试运行
执行以下命令编译并运行:
make compile make run
运行后QEMU窗口会先显示操作系统加载成功!,接着在第二行显示内核已成功启动并运行!,说明Bootloader成功加载并启动了内核。
内容的提问来源于stack exchange,提问作者Federico Occhiochiuso
相关产品推荐
相关产品推荐

