Assembly Language(汇编语言),对于哪些从未深入了解其中的人来说,可谓是高深莫测之极。由于我们的计算机是以汇编语言为基础开发出来的,了解这些内容将会极大地有助于我们弄清CPU的工作原理。
X86 计算机对 IBM PC 原生的完全后向兼容-从系统顶层到加电启动甚至底层硬件电路,实在是令人印象深刻。 这意味着几乎所有的 PC 都能运行1983年以后开发的软件;不过,需要为此付出的代价也是非常之高的。X86 架构由于它的 edge case 和复杂性而“名声大振”。
要明白一台现代 X86 计算机的启动过程,我们需要了解 X86 架构的发展历史,启动过程在 99%的情况下是由 bootloader 处理的。
在我们的 demo 中将专注于16位“实模式”-DOS系统和其他变种操作系统的运行环境。在该模式下,CPU并不支持现代操作系统所具有的各种安全保护措施。运行于其上的程序可以访问系统各个角落甚至修改系统。这使得 DOS 病毒大量泛滥(尽管这些病毒大都不具破坏性,但却很令人厌烦)。
在实模式下,与硬件交互的模型也极其简单。PC 通过外部丰富的软中断与各式各样的硬件交互。
这让使得最初的阶段的系统开发工作容易起来:因为开发者只需知道少许软中断即可完成绝大多数 I/O 操作。
了解这些之后,我们开始我们的第一个 demo:
上面的代码什么意思呢? 其中mov
指令是用来把数据从一个位置传送到另一个地方。在此,我们只是用来在寄存器间传送数据,并未涉及内存空 间。int
指令指代一系列软中断,在这段代码中是 16号中断。
接下来,既然我们已经执行完我们的任务,那么调用hlt
指令停止 CPU 运行。
到现阶段,是不是有点疑惑,我们是怎么就执行到这一步了呢?计算机刚才又是如何执行这些指令的?
实际上,系统启动的第一阶段是启动 BIOS - 用于配置和检测系统硬件。同时, BIOS 输出系统信息给接下来启动的操作系统程序,以便于接下来的硬件检测工作。
假定 BIOS 知道它是从何种设备上启动,那么,它首先会加载该设备 的第一个扇区512字节到内存中的指定位置,然后跳转到此处将控制权移交给下一个启动程序。
在上面的 demo 中,程序仅读取了512字节的有效载荷。如果我们需要执行的程序超过512字节大小,怎么办呢?
有幸的是,BIOS 可以通过调用 13号 int 中断,来访问系统中的磁盘驱动器。
上述代码,加载虚拟磁盘的下一扇区 ,然后跳转到该处。13号 int 中断 API十分简洁,透露出计算机存储器工作的底层细节(尽管flsh存储器广泛使用,众多的数值依旧保留以保持兼容)。
BIOS 提供的服务极其的丰富,这有一个非常棒的参考资料:http://www.ctyme.com/intr/rb-0608.htm
希望这是进入 Assembly Language 的有趣开端,更多精彩,敬请期待 ......
磁盘 - 磁盘扇区写入参数定义
AH = 03h AL = 写入的扇区数 (必须非零) CH = 柱面数低8位 CL = 1-63扇区号 (bits 0-5) 柱面数的高2位 (6-7位, 只用于硬盘hard disk only) DH = 磁头数 DL = 驱动器编号 (磁盘为硬盘驱动器时第7位置位) ES:BX -> 数据缓冲区
返回值: CF 写入错误时置位 CF 写入成功时清除置位 AH = 磁盘状态 AL = 传输的扇区数 (仅当某些BIOS的 CF 置位时有效 )
原文:https://blog.benjojo.co.uk/post/interactive-x86-bootloader-tutorial (文章略有删改) 翻译: 看雪翻译小组 StrokMitream 校对 :
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2019-2-2 15:35
被admin编辑
,原因: 图片本地化