这也是闲得无聊,不知道在哪翻到了雷军当年写的 RI.ASM 源码。早就听说过雷总是汇编高手,我就想着花半天时间研究一下。
说实话,我是写 Python 的,汇编那点东西大学毕业后基本全还给老师了。打开代码一看,满屏的 AX、BX、INT 21h,看得我头皮发麻。好在现在有 AI 能帮我逐行解释,不懂的硬件端口我就百度查,就这么硬啃了半天,算是勉强看懂了他在干什么。
下面我就顺着代码的逻辑,用愚蠢的 Python 的思维强行解释一波(如果有汇编大神路过,求轻喷)。
这一块很有意思,他在手动维护版本日志。特别是 V2.12 提到修复了 8259 初始化的严重错误,说明这程序是直接在操作硬件中断控制器的,这在当年应该也属于极其底层的操作了吧。
接下来是程序的入口。
org 100h 说明这是个 COM 文件,我真是第一次见这种格式。然后 jmp Main 是为了跳过前面的驻留数据区,直接执行初始化代码。
然后是核心逻辑,关于键盘中断的劫持。
这里他定义了一个 newINT9 过程。DOS 时代的驻留程序的标准操作。先用 pushf 保存标志位,然后用 call far 调用旧的中断处理程序。无论你按什么键,系统先处理,处理完了他再检查是不是他设定的热键。如果不是,就让系统正常响应,这样才不会导致键盘失灵。
这里是在直接读取 BIOS 数据区。地址 0040:0017 在 PC 体系结构里专门用来存放键盘状态字节,每一位对应一个键的状态,比如左 Shift、右 Alt 等。他直接去内存里读这个字节,和预设的 HotKey 变量做按位与运算,来判断你有没有按下他规定的组合键。
这里面的 RestoreMCB 让我看了很久。MCB 是内存控制块,DOS 管理内存是用链表连起来的。如果强行杀掉一个程序,链表就会断,系统立马死机。雷军是在手动修复这个链表,把被杀掉程序的内存标记为空闲,并把前后节点接上。
还有那个 Init8259,出现了大量的 out 指令。
这是在对 8259 可编程中断控制器进行编程。20h 和 A0h 是硬件端口地址。在复位硬件中断芯片,确保清理完内存后,鼠标键盘还能正常发中断信号。
这里在内存里检查标志位,因为 x86 是小端序,用的是雷拼音 LEI 的倒序 IE。这是在防止程序重复运行,如果内存里已经有这个标志了,就提示用户不要重复加载。
这里没有用 DOS 的09号功能调用去打印字符串,而是用 BIOS 的 int 10h 或者直接写显存来控制屏幕颜色和滚动。
总结下来,这段代码逻辑简练,但涉及了内存链表管理、中断向量表劫持、硬件端口操作和 BIOS 数据区读取。放在那个年代,确实是把机器性能榨干了。