- 计算机由五大部件组成:控制器、运算器(二者组成CPU)、存储器、输入设备、输出设备
L2 揭开钢琴的盖子
计算机由五大部件组成:控制器、运算器(二者组成CPU)、存储器、输入设备、输出设备
计算机如何工作:重复取指、执行的操作(见计算机组成原理)
由前所述,计算机是通过不断地取指、执行操作来工作的,那么在计算机刚启动时,就应该有一个初始的IP,指向最初的工作内容,下图以x86为例进行介绍。
由CS和IP找到ROM BIOS(Basic Input Output System)映射区,然后找到引导扇区(磁盘0磁道0扇区),从引导扇区开始运行第一个程序。
bootsect.s
下面是引导扇区的代码,bootsect.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80.globl begtext, begdata, begbss, endtext, enddata, endbss
.text //文本段
begtext:
.data //数据段
begdata:
.bss //未初始化数据段
begbss:
.text
SETUPLEN = 4 ! setup程序代码占用扇区数
BOOTSEG = 0x07c0 ! bootsect.s程序代码所在内存原始地址
INITSEG = 0x9000 ! 将bootsect.s移动到0x9000处
SETUPSEG = 0x9020 ! setup程序开始的地址
entry _start //关键字entry告诉链接器“程序入口”
_start:
! 下面这段代码将bootsect.s的程序代码从0x07c0处挪动到0x9000处
mov ax,#BOOTSEG
mov ds,ax //给了bootsect.s代码原地址
mov ax,#INITSEG
mov es,ax //给了bottsect.s代码目标地址
mov cx,#256 //bootsect.s程序代码的字数
sub si,si
sub di,di
rep movw //将0x07c0:0x0000处的256个字挪动到0x9000:0x0000处
! 挪动完成后从0x9000的go标号处开始执行
jmpi go,INITSEG //将代码挪动完成后间接跳转到go标号处执行挪动的代码
go: mov ax,cs
mov ds,ax !设置ds=es=cs
mov es,ax
! 加载setup.s程序,将setup程序读到0x9020:0x0000处
load_setup:
mov dx,#0x0000 ! drive 0, head 0
mov cx,#0x0002 ! sector 2, track 0;从第2个扇区开始读setup的代码
mov bx,#0x0200 ! address = 512, in INITSEG
mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors;从第2个扇区开始读4个扇区
int 0x13 // BIOS中断
jnc ok_load_setup ! ok - continue
!加载错误
mov dx,#0x0000
mov ax,#0x0000 //复位
int 0x13
j load_setup //重读
! 成功将setup.s程序读到0x9020:0x0000处后,输出一些信息,这里输出显示"FOS is Loading..."
! 接着读入system模块到0x1000:0x0000处;
! 最后间接跳转到0x9020:0x0000处,执行setup.s代码
ok_load_setup:
mov ah,#0x03 ! read cursor pos
xor bh,bh
int 0x10 //读光标
mov cx,#23 //字符串长度为17,加上三个换行加回车的6个字符
mov bx,#0x000c ! page 0, attribute c
mov bp,#msg1 ! es:bp 指向待显示字符串
mov ax,#0x1301 ! write string, move cursor
int 0x10 //显示字符
mov ax,#SYSSEG //SYSSEG = 0x1000
mov es,ax
call read_it //读入system模块
jmpi 0,SETUPSEG //间接跳转到0x9020:0x0000处,执行setup.s
msg1:
.byte 13,10
.ascii "FOS is Loading..."
.byte 13,10,13,10
.org 510
boot_flag:
.word 0xAA55
.text
endtext:
.data
enddata:
.bss
endbss:总结bootsect.s的功能:将bootsect.s的程序代码从0x07c0处挪动到0x9000处,然后跳转到go标号处开始执行;再将setup.s程序读到0x9020:0x0000处(bootsect代码是256个字,512个字节,0x90000+0x200=0x90200),并读入system模块;最后跳转到0x9020:0x0000处执行setup.s代码。之所以要将bootsect.s的程序代码从0x07c0处挪动到0x9000处是因为,如果不挪动bootsect.s程序代码,那么在读入system模块的时候,system模块的代码会将bootsect.s的程序代码覆盖掉。