❤️💕💕真正动手时间操作系统,从应用软件出发"进入操作系统",成为掌握计算机关键技术的工程师。Myblog:http://nsddd.top
[TOC]
-
x86
PC刚开机时CPU处于实模式- 和保护模式对应,实模式寻址CS:IP(CS左移四位+IP)
-
开机时,
CS = 0xFFFF
,IP = 0x0000
-
寻址
0xFFFF0
(ROM BIOS映射区) -
检查RAM,键盘,显示器,软硬磁盘
-
将磁盘0磁道0扇区读入
0x7c00
处- 0磁盘、0扇区就是操作系统的引导扇区
-
设置
cs = 0x07c0
,ip = 0x0000
引导扇区的代码存放:
bootsect.s
这是一个汇编语言,汇编语言能指定int
等基本数据类型存放的地址,而高级语言没办法做到。
-
init
-
boot:和系统的引导有关
-
fs:存放Linux支持的文件系统代码
-
include:存放Linux核心需要的头文件
-
kernel:和系统内核相关的源码
-
lib:存放库代码
-
makefile:编译文件
-
mm:和内存管理相关的代码
-
tools:和工具相关的代码
8086汇编实运行在cpu的实模式下,他的寻址方式是 $$ 物理地址 = 段基址<<4 + 段内偏移地址 $$ 下面一次介绍8086汇编的寄存器,寻址模式和指令。
在8086的架构中,一共有14个16位的寄存器,其中ax,bx,cx,dx
是通用寄存器,可以拆成8个8位的寄存器。cs,ds,es,ss
是段寄存器用于寻址,具体内容后面再说。IP
寄存器和cs
寄存器结合指向下一条指令的地址。si,di,bp,sp
用于和段寄存器结合来寻址。状态寄存器具体内容是:进位标志CF、奇偶标志PF、辅助标志AF、为零标志ZF、符号标志SF、追踪标志TF、中断允许标志IF、方向标志DF、溢出标志OF。下面这几个寄存器的图,来自维基百科:
在8086的cpu中寄存器最高有16位,但是地址总线的位数却是20位,这样就导致了只有16位的寄存器无法来寻址20位的地址空间,所以在8086中的寻址方式变成了(这里的物理地址是硬件的真实地址,直接对硬件寻址):
$$
物理地址 = 段地址 << 4 + 段内偏移
$$
例如 段地址为0xf000
,段内偏移为0x1234
,得到的物理地址是0xf1234
。
在8086中cs
和ip
指向下一条指令的地址,cs
是段地址,ip
是段内偏移,同样的ss
和sp
指向栈顶。
具体在指令中如何寻址这里不做介绍。
在8086中指令的原操作数在右边,目标操作数载左边。
mov ax, #0x000f
这条指令是将十六进制数0x000f
放到寄存器ax
中。
mov [0], ax
在这里[0]
的地址是以ds
为段寄存器,以[offest]
里面的offest为段内偏移得到的。
具体内容不做介绍。
在linux-0.11中利用BIOS中断来加载内核,BIOS中断在8086中使用int
指令可以调用,例如下面的程序可以获得光标的位置。
mov ah,#0x03
xor bh,bh
int 0x10
上面的程序调用了BIOS的0x10
中断的0x03
功能号,返回的是光标的位置保存在寄存器dx
中。
BIOS中断的全部功能可以在下面的网站中轻松查到:
在8086的实模式下,最大的寻址空间只有20位(1MB大小),随着硬件的发展,内存越来越大20位的空间不够了,同时在实模式下寻址的是物理地址,没有内存进行保护,存在安全隐患。所以,出现了保护模式。
在保护模式下,通过使用虚拟地址,程序可以使用超过实际大小的内存容量,同时数据的使用也更加安全。
通过选择器查找GDT或者LDT表的得到基地址,然后加上偏移量就得到了线性地址,也就是我们需要的地址。
下面这个地址里面有大部分的8086的指令: