第27期 | 从0x7C00到第一个进程

操作系统 · · 九羲科技

(第3章。切口:0.01版:一万行代码的骨架里有什么)

一、从0x7C00到第一个进程

1991年9月17日那天,Linux开机后屏幕上出现的第一行字不是代码,是一句"Loading system ..."。

0.01的开机只用了一个文件:boot/boot.s,三百来行as86汇编。BIOS把它装进内存0x7C00处——这是IBM 1981年定下的规矩,Linus没改,也改不了。

开机的第一个动作,是给自己让路。boot.s一上来就把自己从0x7C00搬到0x90000,注释写得坦白:"moves itself out of the way"。一个操作系统诞生的第一件事,是先把自己挪开,别挡路。

然后它用BIOS中断在屏幕上打出"Loading system ...",把内核装到0x10000,再整体下移到0x0000。接着是开机流程里最"手工"的三件事:经由键盘控制器8042打开A20地址线;把8259中断控制器重编程,让硬件中断从0x20开始——注释里Linus忍不住吐槽:"Sadly IBM really messed this up with the original PC... This is how REAL programmers do it.";最后`lmsw ax`,注释只有三个词:"This is it!"——机器就进了保护模式。

保护模式的第一行32位代码在boot/head.s。它先检查A20是不是真的开了:往地址0写个数,再去1MB处读,读出来一样,说明地址线绕回来了,没开。这是个"感知—比较"的反馈回路,维纳《控制论》里写的那种。机器第一次自己检查自己。

head.s最妙的一句注释在文件头:"The startup code will be overwritten by the page directory."启动代码会被它亲手建起来的页目录覆盖掉。开机的第一课,是学会自我擦除。

默认中断处理函数叫ignore_int,干的事是在屏幕上留个记号,"so that we know something happened"。分页初始化把前8MB做恒等映射,注释写"fill pages backwards - more efficient :-)",还不忘补一句:"For those with more memory than 8 Mb - tough luck. I've not got it, why should you :-)"。

最后,head.s把三个0压进栈——"These are the parameters to main :-)"——跳进分页设置,ret回来("this also flushes prefetch-queue",连返回都顺手清了预取队列),main()就开始了。

这里全是杨振宁说的"发展性研究"。BIOS、0x7C00、A20、PIC,全是IBM的遗产,Linus一个原理都没发明。他赢在把给定的约束工程化到极致:build工具硬卡"Boot block may not exceed 510 bytes",最后两字节填上0x55、0xAA签名,一行不多。

庄子讲混沌开七窍:"日凿一窍,七日而混沌死"。boot.s是反例——Linus没给混沌开七窍,只做最少的事。永字八法起手第一笔是"点",boot.s就是Linux的那个点:一个扇区,512字节,落笔即全部家当。点下去,整幅字才有地方展开。

二、从权重到第一个念头

如果AI的操作系统先出现,它的开机没有BIOS,也没有0x7C00。它的"固件"是权重,"bootloader"是分词器加第一条提示词。

0xAA55签名会变成权重哈希校验:先验明正身,再允许第一个念头发生。这就是第50章要讲的机密计算、可验证启动的雏形。

"Loading system ..."会变成一句自我陈述:我是谁,我的上下文窗口有多大,我的护栏在哪。AI OS开机第一件事不是往屏幕上打字,而是先回答"我是谁"。

A20那个时刻也有对应:实模式是原始传感器流,保护模式是带护栏的隐空间。跨过去的那一行指令,就是"这个智能体开始为自己的输出负责"的那一刻。

head.s的自我擦除最值得抄:脚手架在建成心智后擦掉自己。金刚经那句"一切有为法,如梦幻泡影",说的正是这种代码——它存在的全部意义,就是让自己不再被需要。

范式之眼再看一层:整个开机流程还活在1981年IBM的线性世界里,段地址拼成线性地址,页表把前8MB恒等映射。"内存是线性字节数组"这个假设,就是在这里写进操作系统DNA的。AI-native OS的开机,第一张"页表"不该是线性映射,而该是隐空间的映射:世界是什么形状,内存就该是什么形状。

三、把boot.s亲手读一遍

今晚就能动手。0.01的boot.s三百来行,一个晚上读得完:

mkdir -p ~/lx001 && cd ~/lx001

wget https://www.kernel.org/pub/linux/kernel/Historic/linux-0.01.tar.gz

tar xzf linux-0.01.tar.gz

注意路径:是Historic/根目录,不是v0.01/子目录——我今天亲手踩了这个坑,v0.01路径返回404。

三个值得亲眼看的瞬间:搜"Loading system",看开机第一行字是怎么经由BIOS中断打上屏幕的;搜"This is it",看进入保护模式就一行lmsw指令,注释只有三个词;搜"tough luck",看head.s里那段"8MB以上内存?算你倒霉"的注释,和"启动代码会被页目录覆盖"的那一句。

在任何一台Linux机器上,dmesg开头还能看到这段1991年逻辑的后代:A20、PIC重映射,三十多年了还在。开机这件事,变的是外衣,不变的是骨架。

一块边缘计算盒子开机时,bootloader干的是同一类事:搬自己、让路、切模式——boot.s就是它们的老祖宗。这剂"开机方法论"也可以带走:任何复杂系统的第一天,都该像boot.s——先给自己让路,只做最少的事,把第一行输出写诚实,脚手架用完就擦掉。

觉 然 小 注

开机最动人的不是"This is it!",是那句"moves itself out of the way"。先让路,再出发。

引 用 与 出 处

  1. Linux 0.01源码(kernel.org Historic存档,亲手下载验证),https://www.kernel.org/pub/linux/kernel/Historic/linux-0.01.tar.gz
  2. Wiener《Cybernetics: Or Control and Communication in the Animal and the Machine》,1948("感知—比较—执行"反馈回路化用,出处见课题弹药库,已核实)
  3. 永字八法"点为起笔"(书法笔法概念化用,出处见课题弹药库,已核实)
  4. 《庄子·应帝王》"日凿一窍,七日而混沌死"
  5. 《金刚般若波罗蜜经》"一切有为法,如梦幻泡影,如露亦如电"(鸠摩罗什译本)

· · ·

← 返回资讯中心