L2 开始揭开钢琴的盖子

L2 开始揭开钢琴的盖子

1. 计算机打开电源时执行的第一条指令

通常是IP指针(或PC指针)指向的内容,由硬件设计者决定。

以 x86 计算机为例:

  1. x86 PC 刚开机时,CPU处于 实模式,寻址方式为 CS:IP
  2. 开机时,CS = 0xFFFF,IP = 0x0000
  3. ROM BIOS 映射区 寻址,地址为 0xFFFF0
  4. 检查 RAM、键盘、显示器、磁盘、……
  5. 将磁盘的 0 磁道 0 扇区(即操作系统的引导扇区)的 512 字节的内容 读入内存 0x7c00
  6. 设置 CS = 0x07c0,IP = 0x0000
地址内容
0xFFFFFFFF ~ ?ROM BIOS
……
0x100000 ~ 0xF0000[入口] ROM BIOS 映射区
……
? ~ 0x7c00留给 0磁道 0 扇区
……
? ~ 0x00000000……

2. 0x7c00处存放的代码

磁盘的引导扇区(0 磁道 0 扇区)的 512 字节的内容会被读到内存地址 0x7c00 处。其中包括启动设备的信息,存放着开机后执行的第一段可被控制的程序。
操作系统由此开始

2.1 引导扇区代码:bootsect.s

三个重要字段:

BOOTSEG = 0x7c0
INITSEG = 0x9000
SETUPSEG = 0x9020

bootsect.s:

.global begtext, begdata, begbss, endtext, enddata, endbss
.text	// 文本段
begtext:
.data	// 数据段
begdata:
.bss	// 未初始化数据段
begbss:
entry start	// 关键字 entry 告诉链接器 "程序入口"
start:
	mov ax, #BOOTSEG		mov ds, ax
	mov ax, #INITSEG		mov es, ax
	mov cx, #256
	sub si, si				sub di, di
	rep	movw	// 重复移动 256 个字
	jmpi	go, INITSEG	// 段间跳转

得到两个地址 ds:si = 0x7c00 和 es:di = 0x90000。然后将 0x7c00 处的 256 个字移动到 0x90000 处,腾出内存。


go: mov ax, cs // cs = 0x9000
    mov ds, ax	mov es, ax	mov ss, ax	mov sp, #0xff00
load_setup:	// 载入setup模块
	mov dx, #0x0000		mov cx, #0x0002		mov bx, #0x0200
	mov ax, #0x0200+SETUPLEN	int 0x13	// BIOS 中断
	jnc ok_load_setup
	mov dx, #0x0000
	mov ax, #0x0000 // 复位
	int 0x13
	j 	load_setup // 重读

int 0x13 代表读磁盘扇区的中断;
ah = 0x02 - 读磁盘,al = 扇区数量(SETUPLEN = 4),
ch = 柱面号,cl = 开始扇区,
dh = 磁头号,dl = 驱动器号,
es:bx = 内存地址。
即从第二个扇区开始读 4 个扇区,这 4 个扇区就是 setup 模块所在的扇区,读到内存地址 0x90200 处。


Ok_load_setup: // 载入 setup 模块
	mov dl,#0x00	mov ax,#0x0800 // ah = 8
	int 0x13	movch,#0x00	mov sectors,cx
	mov ah,#0x03	xor bh,bh	int 0x10 // 读光标
	mov cx,#24	mov bx,#0x0007 // 7 是显示属性
	mov bp,#msg1	mov ax,#1301	int 0x10 // 显示字符
	mov ax,#SYSSEG // SYSSEG = 0x1000
	mov es,ax
	call read_it // 读入 system 模块
	jmpi 0,SETUPSEG
……
sectors:	.word 0 // 磁道扇区数
msg1: 	.byte 13,10
		.ascii "Loading system..."
		.byte 13,10,13,10

int 0x10 代表显示 logo,即显示 msg1 中的内容。同时,cx = 24 代表输出的字符数量。
最后 jmpi 0,SETUPSEG,即跳转至 setup 对应的内存地址执行。


read_it:	mov ax,es	cmp ax,#ENDSEG	jb ok1_read
			ret
ok1_read:
	mov ax,sectors
	sub ax,sread // sread 是当前已读扇区数,ax 是未读扇区数
	call read_track // 读磁道

读取 system 模块的相关代码。

3. 小结

打开电源,首先执行 boot(引导扇区的内容),随后 boot 会完成 setup 的读取工作以及 system 的读取工作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值