为什么程序要载入内存
CPU 的硬件电路被设计成只能运行处于内存中的程序,这样做的原因,首先是内存比较快,且容量大。其次为了方式统一,类似接口,存储介质很多(硬盘,软盘,U盘),操作系统跟硬件不需要付出额外努力去支持。
什么是载入内存
- 程序被加载器(软件或者硬件)加载到内存的某个区域
- CPU的cs:ip寄存器被指向这个程序的起始地址
BIOS(基本输入输出系统,Base Input & Output System)
实模式下的1MB内存布局
Intel 8086有20条地址总线,可以访问1MB的内存空间,2的20次方。
0-0x9FFFF对应DRAM(动态随机访问内存:dynamic random access memory),640kb;0xF0000-0xFFFFF对应的是ROM,里面存的是BIOS的代码,64kb;外设需要地址总线访问,提前预留一部分空间给外设、显存、硬盘控制器等,地址总线上的其余可用地址留给DRAM(我们眼中的物理内存)。
注:如果地址总线不够用,物理内存多大都没用。
BIOS由硬件加载,入口地址是0xFFFF0
CPU如何执行BIOS代码,即CPU中的cs:ip如何组合成0xFFFF0 ?
接电一瞬间,CPU的cs:ip寄存器被强制初始化为0xF000: 0xFFF0,由于开机时处于实模式,所以段基址要乘16,也就是左移4位,即1111 0000 0000 0000左移4位–>1111 0000 0000 0000 0000 为0xF0000+0xFFF0 = 0xFFFF0。此处是跳转指令 jmp far f000:e05b,跳向0xfe05b,这是BIOS代码真正执行的位置。
BIOS校验启动盘中位于0盘0道1扇区的内容
0盘0道1扇区本质上是0扇区(为什么为1,硬盘扇区表示法的CHS法),如果此扇区末尾两个字节分别是魔数0x55, 0xaa就认为此扇区存在可执行程序(主引导记录MBR),加载地址0x7c00(jmp 0:0x7c00)
MBR相关
MBR大小必须是512字节,为了保证两个魔数出现在末尾,即510字节、511字节处,并且bochs模拟的X86是小端字节序,所以最后两个字节是0xaa55,拆开就是0x55、0xaa。
NASM预留关键字$$$和$$$$
$表示本行代码前的标号,$$表示本section的起始地址,如果section用了vstart=xxxx修饰,$$就是此section的虚拟地址xxxx,$就是以xxxx为起始地址的顺延。如果没有定义section,nasm默认代码全部为一个section,起始地址为0。
NASM用法
nasm -f
-o 用来指定输出可执行文件的名称,-f 用来指定输出可执行文件的格式,格式关注 bin 和 elf 格式,bin是默认输出格式,指纯二进制;elf是二进制可执行文件,里面掺杂了程序的内存布局,位置等信息,有一些与操作指令无关。
程序运行
1 | 进入root账户中的bochs-2.7文件夹 |
写入mbr.S
1 | ;主引导程序 |
使用nasm编译
1 | nasm -o mbr.bin mbr.S |
将mbr.bin写入硬盘中
1 | dd if=/root/bochs-2.7/mbr.bin of=/root/bochs-2.7/hd60M.img bs=512 count=1 conv=notrunc //输入 |
再次运行bochs
输出1 MBR
此章节结束