自己动手写操作系统-笔记一

一、CPU工作原理


CPU大体可以分为三个部分:控制单元、运算单元、存储单元

控制单元大致由指令寄存器IR(instruction register)、指令译码器ID(instruction decoder)、操作控制器OC(operation controller)组成。

控制单元取下一条指令,该指令地址在程序计数器PC中,在X86CPU中就是cs:ip。读取ip寄存器后将此地址送上地址总线,CPU根据此地址变得到了指令,存入IR中。

ID根据指令格式检查IR中的指令,先确定操作码,再检查操作数类型,若是在内存中,就将响应操作数从内存中取回放入到自己的存储单元中,若操作数在寄存器中

就直接使用了。下一步,OC给运算单元下指令开始工作,于是运算单元开始执行真正的指令。ip寄存器被加上当前指令大小,指向下一条指令。接着控制单元取下一条

指令,开始无休止的循环工作。

 

二、实模式下CPU寻址方式

1.寄存器寻址

mul dx

2.立即数寻址

mov ax, 0xff

3.内存寻址

内存寻址又分为:

3.1 直接寻址

mov ax, [ds:0x1234]

3.2 基址寻址

sub sp, 2

mov [sp], ax

3.3 变址寻址

mov [si + 0x1234], ax

3.4 基址变址寻址

mov [bx + di], ax

三、IO接口

IO接口是连接CPU和外部设备的逻辑控制部件。

输入输出控制中心(I/O control hub,ICH):CPU访问多个IO接口的逻辑需要ICH控制。

in和out指令的目的操作数和源操作数必须是dx,ax

in ax, dx

out dx, ax

根据操作数位数可以选择使用ax或者al。

1.显卡

把需要显示的内容写到显存中即可。

显卡各种模式内存分布:

显存地址分布
起始 结束 大小 用途
C0000 C7FFF 32KB 显示适配器BIOS
B8000 BFFFF 32KB 用于文本模式显示适配器
B0000 B7FFF 32KB 用于黑白显示适配器
A0000 AFFFF 64KB 用于彩色显示适配器

 

 

 

 

 

在文本模式下每个字符用连续的两个字节表示,高字节用于表示字符的属性(例如前景色、背景色等等)。

2.硬盘

磁头、盘片、磁道、柱面、扇区

扇区是硬盘存储数据的基本单位,固定为512字节。

各磁道内扇区都是以1为起始编号,并且仅限于本磁道内有效,所以各个磁道内的扇区编号都相同,

磁头号、磁道号、扇区号定位唯一扇区。

硬盘控制器端口:

硬盘主要端口寄存器command block register
IO端口 端口用途
primary通道 secondary通道 读操作时 写操作时
0x1f0 0x170 data data
0x1f1 0x171 error features
0x1f2 0x172 sector count sector count
0x1f3 0x173 LBA low LBA low
ox1f4 0x174 LBA mid LBA mid
0x1f5 0x175 LBA high LBA high
0x1f6 0x176 device device
0x1f7 0x177 status command

 

 

 

 

 

 

 

 

 

LBA有两种:

一是LBA28使用28bit来描述一个扇区的地址

二是LBA48使用48bit来描述一个扇区的地址

LBA low、mid、high寄存器分别存储28位地址的0-7、8-15、16-23位,

device寄存器是个杂项,它的低4位用来存储LBA地址的24-27位。

device寄存器和status寄存器:

 

一般硬盘操作顺序:

最主要的顺序就是command寄存器一定要最后写,因为一旦command寄存器被写入后,硬盘就开始干活了。

①先选择通道,往该通道的sector count寄存器中写入带操作的扇区

②往该通道的三个LBA寄存器中写入扇区起始地址的低24位

③往device寄存器中写入LBA地址的24-27位,并置第6位为1,使其成为LBA模式,设置第4位选择操作的硬盘

④往该通道的command寄存器中写入操作命令

⑤读取该通道上的status寄存器,判断硬盘工作是否完成。

⑥如果以上步骤是读硬盘,进入下一步骤,否则,完工。

⑦将硬盘数据读出。

最后送上一段MBR程序中的一个操作硬盘片段,它的作用是将硬盘中的加载器程序读入内存中,首地址为0x900

 

 1 mov eax, 0x2
 2 mov bx, 0x900
 3 mov cx, 1
 4 call rd_disk_m_16
 5 jmp 0x900
 6 
 7 mov esi, eax
 8 mov di, cx
 9 ;设置要读取的扇区数
10 mov dx, 0x1f2
11 mov al, cl
12 out dx, al
13 
14 mov eax, esi
15 
16 ;将LBA地址存入0x1f3-0x1f6
17 mov dx, 0x1f3
18 out dx, al
19 
20 mov cl, 8
21 shr eax, cl
22 mov dx, 0x1f4
23 out dx, al
24 
25 shr eax, cl
26 mov dx, 0x1f5
27 out dx, al
28 
29 shr eax, cl
30 and al, 0x0f
31 or al, 0xe0
32 mov dx, 0x1f6
33 out dx, al
34 
35 ;向端口写入读命令
36 mov dx, 0x1f7
37 mov al, 0x20
38 out dx, al
39 
40 ;检测硬盘状态
41 .not_ready:
42 nop
43 in al, dx
44 and al, 0x88
45 cmp al, 0x80
46 jnz .not_ready
47 
48 ;从端口0x1f0读取数据
49 mov ax, di
50 mov dx, 256
51 mul dx
52 mov cx, ax
53 mov dx, 0x1f0
54 .go_on_read:
55 in ax, dx
56 mov [bx], ax
57 add bx. 2
58 loop .go_on_read
59 ret
60 times 510-($-$$) db 0
61 db 0x55, 0xaa

 

posted @ 2017-12-10 20:51  CLAYJJ  阅读(957)  评论(0编辑  收藏  举报