基于 Free Pascal 从零编写裸机操作系统(一)
前言绝大多数入门操作系统教程都会选用 C 语言很少有人尝试用 Pascal 开发裸内核。OSDev 官网提供了一套完整的 Free Pascal Bare Bones 最小操作系统示例无需依赖 DOS、Linux、Windows 标准库完全运行在 32 位保护模式下兼容 Multiboot 引导规范能直接被 GRUB、QEMU 加载。本文仅拆解全部源码汇编入口、控制台驱动、内核主程序、Multiboot 规范定义编译、链接、镜像制作、QEMU 运行脚本不在本文介绍范围。 参考原文https://wiki.osdev.org/Pascal_Bare_Bones前置说明编译器Free PascalFPC嵌入式裸机编译目标架构x86 32 位保护模式显示VGA 文本缓冲区0xB8000引导Multiboot v1 标准兼容 GRUB无标准库不能使用WriteLn、MemAlloc等系统相关函数所有 IO、内存读写手动实现一、汇编入口文件stub.asm作用声明 Multiboot 头部让 GRUB 识别这是合法内核镜像切换 32 位保护模式环境设置栈导出符号供 Pascal 调用跳转至 Pascal 内核主函数MainKernelnasm;///////////////////////////////////////////////////////// ;// // ;// Freepascal barebone OS // ;// stub.asm // ;// // ;///////////////////////////////////////////////////////// ;// ;// By: De Deyn Kim kimdedeynskynet.be ;// License: Public domain ;// ; ; Kernel stub ; ; ; We are in 32bits protected mode ; [bits 32] ; ; Export entrypoint ; [global kstart] ; ; Import kernel entrypoint ; [extern kmain] ; ; Posible multiboot header flags ; MULTIBOOT_MODULE_ALIGN equ 10 MULTIBOOT_MEMORY_MAP equ 11 MULTIBOOT_GRAPHICS_FIELDS equ 12 MULTIBOOT_ADDRESS_FIELDS equ 116 ; ; Multiboot header defines ; MULTIBOOT_HEADER_MAGIC equ 0x1BADB002 MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_MODULE_ALIGN | MULTIBOOT_MEMORY_MAP MULTIBOOT_HEADER_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC MULTIBOOT_HEADER_FLAGS) ; ; Kernel stack size ; KERNEL_STACKSIZE equ 0x4000 section .text ; ; Multiboot header ; align 4 dd MULTIBOOT_HEADER_MAGIC dd MULTIBOOT_HEADER_FLAGS dd MULTIBOOT_HEADER_CHECKSUM ; ; Entrypoint ; kstart: mov esp, KERNEL_STACKKERNEL_STACKSIZE ;Create kernel stack push eax ;Multiboot magic number push ebx ;Multiboot info call kmain ;Call kernel entrypoint cli ;Clear interrupts hlt ;Halt machine section .bss ; ; Kernel stack location ; align 32 KERNEL_STACK: resb KERNEL_STACKSIZE源码关键点解读Multiboot 头三行 magic/flags/checksum 是 GRUB 识别内核的核心位置不能偏移.bss段预留 16KB 静态栈裸机无动态内存分配栈必须静态声明GRUB 会把内存、磁盘等硬件信息结构体地址存入ebx入栈传递给 Pascal 内核内核执行完毕后死循环停机防止指令越界。二、VGA 控制台驱动单元console.pas作用封装底层 VGA 文本缓冲区操作实现清屏、打印字符、字符串、数字、十六进制是内核唯一输出接口对外导出可被汇编 / 内核主程序调用的过程。pascal{ ///////////////////////////////////////////////////////// // // // Freepascal barebone OS // // console.pas // // // ///////////////////////////////////////////////////////// // // By: De Deyn Kim kimdedeynskynet.be // License: Public domain // } unit console; interface var xpos: Integer 0; ypos: Integer 0; procedure kclearscreen(); procedure kwritechr(c: Char); procedure kwritestr(s: PChar); procedure kwriteint(i: Integer); procedure kwritedword(i: DWORD); implementation var vidmem: PChar PChar($b8000); procedure kclearscreen(); [public, alias: kclearscreen]; var i: Integer; begin for i : 0 to 3999 do vidmem[i] : #0; end; procedure kwritechr(c: Char); [public, alias: kwritechr]; var offset: Integer; begin if (ypos 24) then ypos : 0; if (xpos 79) then xpos : 0; offset : (xpos shl 1) (ypos * 160); vidmem[offset] : c; offset 1; vidmem[offset] : #7; offset 1; xpos : (offset mod 160); ypos : (offset - xpos) div 160; xpos : xpos shr 1; end; procedure kwritestr(s: PChar); [public, alias: kwritestr]; var offset, i: Integer; begin if (ypos 24) then ypos : 0; if (xpos 79) then xpos : 0; offset : (xpos shl 1) (ypos * 160); i : 0; while (s[i] Char($0)) do begin vidmem[offset] : s[i]; offset 1; vidmem[offset] : #7; offset 1; i 1; end; xpos : (offset mod 160); ypos : (offset - xpos) div 160; xpos : xpos shr 1; end; procedure kwriteint(i: Integer); [public, alias: kwriteint]; var buffer: array [0..11] of Char; str: PChar; digit: DWORD; minus: Boolean; begin str : buffer[11]; str^ : #0; if (i 0) then begin digit : -i; minus : True; end else begin digit : i; minus : False; end; repeat Dec(str); str^ : Char((digit mod 10) Byte(0)); digit : digit div 10; until (digit 0); if (minus) then begin Dec(str); str^ : -; end; kwritestr(str); end; procedure kwritedword(i: DWORD); [public, alias: kwritedword]; var buffer: array [0..11] of Char; str: PChar; digit: DWORD; begin for digit : 0 to 10 do buffer[digit] : 0; str : buffer[11]; str^ : #0; digit : i; repeat Dec(str); str^ : Char((digit mod 10) Byte(0)); digit : digit div 10; until (digit 0); kwritestr(str); end; end.源码关键点解读VGA_BUFFER_ADDR $B8000是 x86 实模式 / 保护模式通用文本显存地址无需 BIOS 中断每个字符占用 2 字节低字节 ASCII高字节颜色属性内置自动滚动逻辑打印超出 25 行时整体上移一行清空底部PChar兼容 C 字符串0 终止符方便和汇编交互数字打印不依赖标准库SysUtils手动实现进制转换缓冲区。三、Multiboot 规范常量定义multiboot.pas作用定义 Multiboot v1 标准的内存信息结构体、魔数、标志位内核主程序读取 GRUB 传入的硬件信息时使用。pascalunit multiboot; interface const KERNEL_STACKSIZE $4000; MULTIBOOT_BOOTLOADER_MAGIC $2BADB002; type Pelf_section_header_table_t ^elf_section_header_table_t; elf_section_header_table_t packed record num: DWORD; size: DWORD; addr: DWORD; shndx: DWORD; end; Pmultiboot_info_t ^multiboot_info_t; multiboot_info_t packed record flags: DWORD; mem_lower: DWORD; { Amount of memory available below 1mb } mem_upper: DWORD; { Amount of memory available above 1mb } boot_device: DWORD; cmdline: DWORD; mods_count: DWORD; mods_addr: DWORD; elf_sec: elf_section_header_table_t; mmap_length: DWORD; mmap_addr: DWORD; end; Pmodule_t ^module_t; module_t packed record mod_start: DWORD; mod_end: DWORD; name: DWORD; reserved: DWORD; end; Pmemory_map_t ^memory_map_t; memory_map_t packed record size: DWORD; { You can declare these two as a single qword if your compiler supports it } base_addr_low: DWORD; base_addr_high: DWORD; { And again, these can be made into one qword variable. } length_low: DWORD; length_high: DWORD; mtype: DWORD; end; implementation end.源码关键点解读packed record禁用内存对齐严格匹配 Multiboot 二进制布局mem_lower/mem_upper是本示例核心用于计算整机物理内存大小结构体指针由汇编kernel_entry.asm中ebx传入内核主程序。四、内核主程序kernel.pas作用程序入口MainKernel整合控制台、Multiboot 模块完成初始化、硬件信息打印、停机逻辑是整个操作系统顶层业务代码。pascal{ ///////////////////////////////////////////////////////// // // // Freepascal barebone OS // // kernel.pas // // // ///////////////////////////////////////////////////////// // // By: De Deyn Kim kimdedeynskynet.be // License: Public domain // } unit kernel; interface uses multiboot, console; procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: DWORD); stdcall; implementation procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: DWORD); stdcall; [public, alias: kmain]; begin kclearscreen(); kwritestr(Freepascal barebone OS booted!); xpos : 0; ypos 1; if (mbmagic MULTIBOOT_BOOTLOADER_MAGIC) then begin kwritestr(Halting system, a multiboot-compliant boot loader needed!); asm cli hlt end; end else begin kwritestr(Booted by a multiboot-compliant boot loader!); xpos : 0; ypos 2; kwritestr(Multiboot information:); xpos : 0; ypos 2; kwritestr( Lower memory ); kwriteint(mbinfo^.mem_lower); kwritestr(KB); xpos : 0; ypos 1; kwritestr( Higher memory ); kwriteint(mbinfo^.mem_upper); kwritestr(KB); xpos : 0; ypos 1; kwritestr( Total memory ); kwriteint(((mbinfo^.mem_upper 1000) div 1024) 1); kwritestr(MB); end; asm loop: jmp loop end; end; end.源码关键点解读MainKernel带[public]导出汇编call MainKernel可直接调用入参PMultibootInfo接收 GRUB 传入的硬件信息指针先校验 Multiboot 魔数防止非 GRUB 引导导致内存读取崩溃纯汇编内嵌clihlt关闭中断停机裸机无操作系统异常处理末尾默认begin..end是 FPC 标准程序占位裸机环境不会触发执行。五、整体源码结构梳理plaintextPascal-BareBones/ ├─ kernel_entry.asm 汇编引导入口Multiboot头 ├─ multiboot.pas Multiboot硬件信息结构体定义 ├─ console.pas VGA控制台底层驱动单元 └─ kernel.pas 内核主程序系统业务逻辑六、源码运行逻辑完整流程GRUB 加载镜像识别.multiboot头部把硬件信息存入 EBX执行kernel_entry.asm初始化栈压入 EBX 指针调用MainKernelPascal 内核执行清屏 → 校验 Multiboot 合法性 → 打印内存硬件信息 → 死循环停机所有屏幕输出均调用console.pas封装的 VGA 显存操作无任何 BIOS/DOS 系统调用。七、拓展改造方向基于现有源码完善 VGA 颜色属性实现彩色文字输出增加键盘中断 IRQ1 驱动实现字符输入新增简单堆内存管理器替代静态变量扩展 Multiboot 模块读取磁盘、模块加载信息增加简单多任务调度框架基于 Pascal 过程实现线程切换。结尾这套源码完整实现了最小可用 Pascal 裸内核全程不依赖任何操作系统标准库所有硬件交互代码自主可控。相比 C 语言 OS 教程Pascal 强类型、单元模块化的特性让底层硬件结构体、驱动代码可读性更高。下一篇博文我会讲解编译脚本、链接脚本、GRUB 镜像制作与 QEMU 运行完整流程。

相关新闻

【方达炬治学】方达炬:在地球表面设置22°气温生命环境线,作为生命宜居带,确立生命活动周期同太阳活动相适应、及应对太阳工程日光威胁。

【方达炬治学】方达炬:在地球表面设置22°气温生命环境线,作为生命宜居带,确立生命活动周期同太阳活动相适应、及应对太阳工程日光威胁。

【方达炬治学】方达炬:在地球表面设置22气温生命环境线,作为生命宜居带,确立生命活动周期同太阳活动相适应、及应对太阳工程日光威胁。

2026/8/1 3:41:20阅读更多 →
应届生注意:别浪费在校时间,AI能力将成为求职分水岭

应届生注意:别浪费在校时间,AI能力将成为求职分水岭

2026届全国普通高校毕业生规模达1270万人,同比增加48万,再创历史新高。 几乎同一时间,国家发改委在2026世界人工智能大会上公布:重点行业人工智能整体渗透率突破80%,今年相关产业增速预计超30%;工信部同步披…

2026/8/1 3:41:20阅读更多 →
从“对话“到“执行“:MCP协议如何统一AI Agent与真实世界的连接方式?

从“对话“到“执行“:MCP协议如何统一AI Agent与真实世界的连接方式?

从"对话"到"执行":MCP协议如何统一AI Agent与真实世界的连接方式?当AI Agent只会"纸上谈兵"的时代终结,MCP协议正在成为连接认知与行动的统一桥梁。本文深入解析MCP的核心架构、无状态化演进,以及它…

2026/8/1 3:41:20阅读更多 →
ADB解锁智能电视安装限制:从原理到实战的完整指南

ADB解锁智能电视安装限制:从原理到实战的完整指南

1. 问题缘起:当智能电视不再“智能”最近在折腾家里的老款TCL智能电视,想装几个自己常用的App,结果发现应用商店里空空如也,想从U盘安装APK文件,系统直接弹出一个“为保障电视安全,禁止安装来源不明的应用”…

2026/8/1 5:03:50阅读更多 →
ESP32外接SPI Flash选型与集成指南:从扩容需求到实战调试

ESP32外接SPI Flash选型与集成指南:从扩容需求到实战调试

1. 项目概述:为什么ESP32需要外接Flash?如果你玩过ESP32,大概率知道它内部集成了Flash,那为什么还要讨论外接SPI Flash呢?这其实是一个从“够用”到“好用”再到“专业”的进阶问题。很多新手拿到ESP32开发板&#xff…

2026/8/1 5:03:50阅读更多 →
AD24添加官方库

AD24添加官方库

最近看与多同学下载AD24都没有自带的库,需要自己下载,对小白来说挺蒙圈的,我就带大家走一遍吧。 1.首先用浏览器搜索altuim designer,点进去。这是官网,所以不用担心 2.点击右上角头像,用邮箱/QQ号qq.com注册&#xf…

2026/8/1 5:03:50阅读更多 →
数字电路设计核心:从CMOS宽长比到竞争冒险的底层逻辑

数字电路设计核心:从CMOS宽长比到竞争冒险的底层逻辑

1. 从“宽长比”到“线与逻辑”:数字电路设计的底层密码如果你刚开始接触数字电路设计,可能会觉得CMOS管宽长比、OC/OD门、线与逻辑、传输门、竞争冒险、三态门这些名词像一堆散落的拼图,各自独立,难以串联。但当你真正动手去设计…

2026/8/1 5:03:50阅读更多 →
拆解集群账号乱象:一机多号行为识别、客诉溯源与风控优化实践

拆解集群账号乱象:一机多号行为识别、客诉溯源与风控优化实践

在账户安全运营实践中,一类关于短信验证码的异常投诉逐渐呈现出可识别的共性特征:用户主张“本人并未主动注册或登录,却收到了机构下发的 OTP 验证码”。本报告将其抽象为可分析的“异常 OTP 投诉”对象,区分其背后截然不同的风险…

2026/8/1 5:03:50阅读更多 →
Android应用集成VLC播放器:从LibVLC配置到RTSP流媒体实战

Android应用集成VLC播放器:从LibVLC配置到RTSP流媒体实战

1. 项目缘起:为什么要在Android项目里引入VLC? 如果你正在开发一个Android视频播放应用,或者需要在你的App里嵌入一个稳定、强大的播放器组件,那么你大概率已经绕不开一个名字:VLC。市面上播放器方案很多,…

2026/8/1 5:01:50阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/31 20:44:05阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/31 17:41:43阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/31 20:44:05阅读更多 →
无损视频剪辑终极指南:如何实现快速高效的多媒体处理

无损视频剪辑终极指南:如何实现快速高效的多媒体处理

无损视频剪辑终极指南:如何实现快速高效的多媒体处理 【免费下载链接】lossless-cut The swiss army knife of lossless video/audio editing 项目地址: https://gitcode.com/gh_mirrors/lo/lossless-cut 在数字媒体创作领域,视频编辑处理的质量损…

2026/8/1 0:00:10阅读更多 →
AI辅助本科论文写作:8大工具评测与高效使用指南

AI辅助本科论文写作:8大工具评测与高效使用指南

1. 本科生论文写作的AI辅助现状本科毕业论文是每个大学生必须跨越的一道坎。记得我当年写论文时,光是文献检索就花了整整两周时间,打印的参考文献堆满了半个书桌。如今AI技术的发展为学术写作带来了革命性变化,合理使用这些工具可以节省80%以…

2026/8/1 0:00:10阅读更多 →
如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手

如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手

如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手 【免费下载链接】ticket-purchase 大麦自动抢票,支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase 还在为抢不到热门演唱会门票…

2026/8/1 0:00:10阅读更多 →
无损视频剪辑终极指南:如何实现快速高效的多媒体处理

无损视频剪辑终极指南:如何实现快速高效的多媒体处理

无损视频剪辑终极指南:如何实现快速高效的多媒体处理 【免费下载链接】lossless-cut The swiss army knife of lossless video/audio editing 项目地址: https://gitcode.com/gh_mirrors/lo/lossless-cut 在数字媒体创作领域,视频编辑处理的质量损…

2026/8/1 0:00:10阅读更多 →
AI辅助本科论文写作:8大工具评测与高效使用指南

AI辅助本科论文写作:8大工具评测与高效使用指南

1. 本科生论文写作的AI辅助现状本科毕业论文是每个大学生必须跨越的一道坎。记得我当年写论文时,光是文献检索就花了整整两周时间,打印的参考文献堆满了半个书桌。如今AI技术的发展为学术写作带来了革命性变化,合理使用这些工具可以节省80%以…

2026/8/1 0:00:10阅读更多 →
如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手

如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手

如何快速配置大麦自动抢票系统:从零开始搭建Python抢票助手 【免费下载链接】ticket-purchase 大麦自动抢票,支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase 还在为抢不到热门演唱会门票…

2026/8/1 0:00:10阅读更多 →