1、进阶操作系统

什么是操作系统?

windows,unix,linux,macos,android,ios...

操作系统是直接运行于硬件之上的计算机程序。

操作系统用于管理和控制计算机的硬件与软件资源。

操作系统为用户软件的开发提供必要的服务和接口。

现代计算机系统架构:

硬件层-BIOS()-操作系统-用户软件(编译软件)

BIOS-(base input & output system)

BIOS是计算机上电后第一个运行的程序。

BIOS首先检测硬件状态,检测通过后立即进行硬件初始化。

BIOS会在内存中建立中断向量表(提供硬件访问的方法)

BIOS最后将控制权交由主引导程序执行。

注意注意注意:

BIOS不是软件(software),而是固件(firmware)。

固件是固化于硬件中的程序,在硬件出厂前已经烧写固定。

系统启动流程(x86)

上电-运行BIOS-硬件初始化--建立中断向量表--加载主引导程序--软件初始化--加载运行操作系统内核--系统初始化

谁加载BIOS?

BIOS的运行机制:

BIOS存储于ROM中,地址映射为0xF0000-0xFFFFF(实地址)

BIOS的入口地址为:0xFFFF0

硬件电路的特殊设计使得:

开机后,cpu从0xFFFF0处开始执行。

BIOS的最后使命:

按照用户设置扫描各个存储介质(光驱,软驱,U盘,等)

发现主引导区后,将主引导区中的主引导程序载入内存。

主引导程序在内存中的入口地址为0x7c00.

将控制权交由主引导程序执行(jmp 0x7c00)。

思考:BIOS如何在存储介质中寻找主引导区?如何判断引导区中有没有主引导程序?

主引导区(MBR:Master Boot Record)

位置:位于存储介质的最开始位置处,大小为512字节。

特点:前512字节的最后2个有效字节为0x55aa,是否有效的标志。

数据:0x55aa之前的数据被视为主引导程序。

是不是每个存储介质前512字节就一定是主引导区? 否,BIOS会查看是不是0x55aa,是才是

如果判断了是主引导区,那么是不是就一定合法? 否,很可能加载到内存后,执行出错

更详细的启动流程(x86)

运行BIOS--光驱存在MBR?--软驱存在MBR?--硬盘存在MBR?--加载主引导程序(拷贝到Addr:0x7c00)--jmp 0x7c00--软件初始化--加载运行系统内核--系统初始化-run

小结:

BIOS是计算机上电后第一个运行的程序。

BIOS进行必要的初始化,并加载运行主引导程序

主引导程序位于存储介质的最开始512字节处。

主引导程序负责后续初始化,并加载运行操作系统内核。

2、hello,DTOS!

问题:主引导程序是软件还是固件?如果是软件,那么由谁开发?如何开发?

软件。

主引导程序:

一段存储在主引导区(MBR)中的有效代码。

并不固化于硬件,属于操作系统代码的一部分。

启动操作系统内核的桥梁,由汇编程序写成。

代码总量不能超过512个字节(包含0x55aa)。

主引导程序开发:

入口0x7c00--主引导程序(汇编语言)--BIOS中断

入口main--应用程序(c/c++)--os系统调用(API功能函数)

课程实验:

编写一个主引导程序(汇编语言)。

可独立运行与x86架构的主机(无操作系统)。

运行后在屏幕上打印“hello DTOS!”

实现思路:

1、将关键寄存器的值设置为0(mov ax, 0)

2、定义需要打印的数据(db "hello,d.t.os!")

3、打印预定义好的字符数据(int 0x10)

汇编小贴士-

mov: 赋值操作,将右操作数赋值给左操作数

    mov ax, 0;将0赋值给ax寄存器

int:触发中断

    int 0x10;触发0x10中断,对屏幕进行操作

hlt:停止运行,CPU进入暂停状态,不执行任何操作

    hlt:使程序进入睡眠状态

汇编小贴士二

汇编中地址的访问方式:段地址:段内偏移地址

mov byte[0xb800:0x01],0x07;   0xb800:0x01->0xb8000+0x01(左移4位,0x07放进去,占一个字节)

标签:用于标识后续指令的地址(可等同为c语言中的标签)

& vs &&

&表示当前指令行地址,&&表示当前汇编段起始地址

中断调用 vs 函数调用  在屏幕上打印一个字符

mov bx,0x0f【参数】

mov ah,0x0e【参数】

mov al,'c'【数据】

int 0x10 (功能标识)

==>

printf【功能标识】("%c"【参数】, 'c'【数据】);

代码:

org 0x7c00

start:

    mov ax, cs  初始化:置0

    mov ss, ax

    mov ds, ax

    mov es, ax

    mov si,msg

print:

    mov al, [si]  取数据  al保存si执行的内存中的第一个数据

    add si, 1

    cmp al, 0x00

    je last   如果相等,跳转到last jump equal

    mov ah,0x0e

    mov bx, 0x0f

    int 0x10

    jmp print

last:

    hlt

    jmp last

msg:

    db 0x0a, 0x0a 换行

    db "hello, deos!"

    db 0x0a, 0x0a

    timers 510-(&-&&) db 0x00  数据结束符 这行地址减去这段代码开头地址

    db 0x55, 0xaa

如何验证主引导程序?

解决方案设计:

将汇编源码编译为二进制机器码(nasm)

创建虚拟盘(bximage)  输入fd  代表创建虚拟软盘

将二进制代码写入虚拟盘起始位置(dd)

在虚拟机中将虚拟盘作为启动盘执行(vmware)

实验原材料:

nasm  命令:编译汇编代码

nasm boost.asm -o boot.bin

bximage  创建虚拟软盘

bximage a.img -q -fd -size=1.44

bximage a.img(创建a.img) -q(不需要任何交互) -fd(创建的是虚拟软盘) -size=1.44(1.44兆)

dd 将二进制代码写入软盘

dd if=boot.bin of=a.img bs=512 count=1 conv=notrunc

dd if=boot.bin(输入) of=a.img(输出到a.ing虚拟软盘) bs=512(写入512字节)count=1(1个512字节) conv=notrunc(连续写入,不要间隔)

小结:主引导程序的代码量不能超过512字节

主引导程序需要使用汇编语言开发

主引导程序中可以通过BIOS中断使用硬件功能

主引导程序运行于实模式(地址都是实际的物理地址)。 

3、调试环境的搭建

问题:如何调试主引导区的代码?

Bochs(优秀的虚拟机软件)

专业模拟x86架构的虚拟机。

开源且高度可移植,由c++编写完成。

支持操作系统开发过程中的断点调试。

通过简单配置就能够运行绝大多数主流的操作系统。

支持调试功能的Boch版本

1、下载源码:http://sourceforge.net/progects/bochs/files

2、解压缩bochs-2.x.x.tar.gz->bochs-2.x.x

3、进入源码目录:cd bochs-2.x.x

4、./configure --enable-debugger --enable -disasm  配置

5、make

6、sudo make install

安装是没有装gtk开发库

命令 sudo apt-get install libgtk2.0-dev

装上就可以了。

sudo make install

就可以

小贴士:

确定bochs的安装路径(which bochs)

安装vgabios(apt-get install vgabios)

确定vgabios的安装路径(whereis vgabios)

Bochs的启动文件:

#启动为操作系统分配多大内存

megs:32

#镜像文件路径 ROM images:

romimage:file=/usr/local/share/bochs/BIOS-bochs-latest

vgaromimage:file=/user/share/vgabios/vgabios.bin

#what distk images will be used

floppya(软驱):1_44=a.img(虚拟软盘文件),status=inserted(启动虚拟软盘已经插入虚拟机了)

#choose the boot disk

boot:floppy 从软驱启动

#where do wu send log messagers?

# log:bochsout.txt

#disable the mouse

mouse:enable=0

#enable key mapping,using US layout as default

keyboard_mapping:enabled=1,map=/usr/local/share/bochs/keymaps/x11-pc-us.map (map路径)

启动bochs虚拟机:

显示方式:bochs -f bochsrc_file

隐式方式:bochs

    .bochsrc  当前目录下的启动文件名 先找这个

    bochsrc  当前目录下的启动文件名  再找这个

    bochsrc.txt  当前目录下的启动文件名  在找这个

调试环境验证:

命令:which bochs 查看bochs安装到哪里

sudo apt-get install vgabios

E: 有几个软件包无法下载,您可以运行 apt-get update 或者加上 --fix-missing 的选项再试试?

装 vgabios出错

命令:sudo apt-get update 

之后就好了

whereis vgabios

查看vgabios安装到哪里

 bochs

continue

Bochs中的常用调试命令:

命令                    功能            示例

b(break)            设置断点    b 0x7c00

c(continue)        继续执行    c

s(step)                单步执行    s

info b(info break) 查看当前所有断点 info b

info cpu            查看当前cpu状态     info cpu

r(reg)                查看常规寄存器状态 r

sreg                    查看段寄存器状态   sreg 

x/Nuf expression查看内存中的数据   x/2bx 0x7c00

trace on[off]        开关:打印执行的指令 trace on

trace-reg on[off]  开关:打印寄存器的值  trace-reg on

试验:

bochs

break 0x7c00

info break

continue

reg  打印寄存器值 ip寄存器的值0x7c00

eip: 0x00007c00 ip寄存器初始化为主引导程序的入口地址

// [0x00007c00] 0000:7c00 (unk. ctxt): mov ax, cs                ; 8cc8

地址表示0000:7c00  段地址:段内偏移地址

汇编语言中通过短地址+段内偏移地址表示内存地址

8cc8表示编译器编译mov ax, cs 语句得到的16进制数

eax: 0x0000aa55 43605

断点停下来的地方eax寄存器的值是0x0000aa55不是0,上节课将了首先将关键寄存器置0,

而写的是mov ax,cs  ,开始执行时cs寄存器中的值就是0,初始化各个段寄存器,cs寄存器代表代码段,ds代表的是数据段,es代表的是附加数据段,在程序里边并没有具体明显的分段,换句话说数据段和代码段是集中在一起的,全部揉在一起了,因此,才这样赋值,代码段和数据段指的就是同一个内存段了,段的起始地址是:

sreg

es:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed
cs:0x0000,
dh=0x00009300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed
ss:0x0000, dh=0x00009300, dl=0x0000ffff, valid=7
Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed
ds:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed
fs:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed
gs:0x0000, dh=0x00009300, dl=0x0000ffff, valid=1
Data segment, base=0x00000000, limit=0x0000ffff, Read/Write, Accessed
ldtr:0x0000, dh=0x00008200, dl=0x0000ffff, valid=1
tr:0x0000, dh=0x00008b00, dl=0x0000ffff, valid=1
gdtr:base=0x000fb997, limit=0x30

idtr:base=0x00000000, limit=0x3ff

continue

关闭。

break 0x7c00

info break

continue

step

step

x /2bx 0x7c00 读取内存中的值,强大的 命令 8cc8?

trace on  打开开关,每执行一条指令就将执行的指令打印出来

step

step

trace-reg on 打开开关,每运行一条指令之前会将一系列寄存器的值给打印出来然后执行目标指令,执行完又会打印一系列寄存器的值

step

关注一下si寄存器是否发生变化

trace off 关闭开关

trace-reg off 关闭开关

continue

小结:

Bochs是一款专业模拟x86架构的虚拟机。

从源码安装Bochs可以获得调试功能的支持。

Bochs的启动配置文件时正确运行关键。

Bochs的启动配置文件是正确运行关键。

Bochs支持断点调试,其调试命令与GDB类似。

问你的项目东西,不是看你做了什么,而是看你学习能力,你是怎么解决问题的,你的思维,从问题出发,你的思考?

猜你喜欢

转载自blog.csdn.net/WS857707645/article/details/80945107