操作系统

《操作系统真象还原》相关笔记
https://www.cnblogs.com/20135223heweiqin/p/5444617.html

分段原因

段基址+段内偏移地址实现程序重定位

代码段、数据段划分

1、编译器挑选出数据具备的属性,从而根据属性将程序片段分类,比如只读的代码段和可读写的数据段。
2、操作系统设置GDT全局描述符表来构建段描述符,在段描述符中指定段的位置、大小、属性(S字段、TYPE字段等)。
3、操作系统服务CPU中的寄存器以相应的选择子,从而确定指向的段。

实模式vs保护模式

实模式下:段基址+段内偏移地址=物理地址
保护模式下:段基址(选择子索引GDT得到真正段基址)+段内偏移地址=线性地址。
            如果没有开分页功能,线性地址就是物理地址。
            如果开了分页功能,线性地址也叫虚拟地址,通过页表转换得到物理地址。
16位vs32位?

段重叠

两个不同的段可能有重叠的区域。比如0xC05 = 0xC00 + 5 = 0xC02 + 3

段寄存器(存储段基值)

CS(代码段)、DS(数据段)、ES(附加段)、FS(附加段)、GS(附加段)、SS(堆栈段)
实模式:段寄存器指向真实的物理地址
保护模式:段寄存器指向“段选择子”

Linux系统下程序不能在Windows下运行

1、格式不同 Linux:elf(Executable and Linking Format),有节,段信息,程序入口等。Windows: PE(portable executable)格式
2、系统API不同

局部变量放在栈中

全局变量是都可以随时访问,因此放在数据段中。局部变量由于局部性,被放在栈中,随时清理。
函数参数在被调用时才在栈中为其分配内存。
堆:程序运行过程中用于动态分配的内存,是操作系统为每个用户进程规划的。
栈:处理器运行必备的内存空间,硬件必须。软件提供。

大端字节序vs小端字节序

小端字节序:数值的低字节放在内存的低地址处、高对高。例如0x12345678,存储地址从低到高依次为0x78、 0x56...。
            强制转换数据类型时不需要再调整字节了。
大端字节序:数值的低字节放在内存的高地址处、高对低。
            容易判断正负。

中断向量表(IVT)

中断向量表1024字节,每个中断向量4个字节,最多容纳256个中断向量,描述了中断处理程序的段基址和段内偏移地址。
中断向量表0H~1FH项是BIOS中断。
中断向量表的建立由CPU提供原生支持。
启动时中断向量表中的中断例程由BIOS建立,从物理地址0x0000处初始化。BIOS会调用外设ROM中的例程以及初始化代码。
外设ROM规范:0x55 + 0xAA + 512字节为单位的代码长度 + 实际代码
DOS运行在实模式下,可以调用BIOS中断。只占用0x21这个中断号,但是可以通过ah寄存器实现多种功能调用。
Linux内核在进入保护模式后才建立中断例程。保护模式下,中断向量表不存在,取而代之的是中段描述符表(IDT)。 int 0x80,通过eax的值实现不同子功能调用。

访问外设

内存映射(0xA0000~0xFFFFF)或者端口操作
BIOS扫描0xE0000~0xE0000之间的内存,发现以0x55 、0xAA开始的区域,意味着该区域对应的rom中有代码。检查代码大小是否与第三个字节相等。
若无误,执行ROM程序,写中断表。

section & segment

section为节,汇编源码中section或segment修饰、逻辑划分的指令区域或者数据区域。汇编器会把这两个关键字修饰的区域在目标文件中编译成节。
segment称为段,链接器将汇编源码中属性相同的节合并后的section集合,也成为段。诞生于链接成可执行文件阶段。
readelf 命令可以查看文件的头信息。

magic number

用来判断是否为elf文件
识别分区的文件系统,一般是该分区的第二个扇区,也称为超级块。

CPU指令执行

x86架构不能用MOV指令改变CS:IP的值,需要用jmp,call,int,ret实现硬件级的原子操作。
PC(程序计数器)在不同架构中有有不同的表现形式,x86中无具体的寄存器。ARM中有专门的寄存器。

指令集

CISC : x86(Intel AMD 用CISC,但内部实现采取了RISC内核,一条CISC译码成多条RISC指令)
RISC : MIPS(龙芯,用的比较少) ARM(手机处理器) Power(IBM服务器处理器) C6000(数字信号处理器,视频处理)

程序编译、汇编、链接

头文件中只有函数声明,声明告诉编译器:函数返回值类型,参数类型及个数,用来确定分配的栈空间;该函数是外部函数,定义在其它文件,链接阶段分配地址。
gcc -E gt.c //打印出预处理后的文件内容‘
gcc -v gt.c //编译链接详细过程
编译:C代码->汇编代码,ccl完成,.c变成.s
汇编:汇编编译成目标文件 as完成,.s变成.o
链接:目标文件链接成可执行文件 collect2完成,是链接命令ld的封装。

链接阶段从LIBRARY_PATH中找到调用需要的.o文件
ltrace能够跟踪程序运行时调用的库函数 ltrace -S
xxd可以逐字节查看文件

MBR、EBR、DBR、OBR

BIOS完成简单的检测和初始化工作,BIOS加载MBR程序到内存0x7c00,然后跳过去执行。BIOS入口地址0xFFFF0,通电一瞬间cs:ip强制初始化为0xF000:0xFFF0
MBR,主引导记录,固定在整个硬盘最开始的扇区,0盘0道1扇区(CHS方式表示扇区地址,从1开始记。LBA方式从0开始),一般情况一扇区为512字节。
    1)446字节的引导程序和参数
    2)64字节的分区表,每个分区表项占据16个字节
    3)2字节结束标识。0x55,0xAA
    MBR完成之后,从多个次引导程序中选出一个交出控制器。遍历分区表中记录的四个分区,找到合适的次引导程序并交出控制权。
次引导程序:通常情况下是操作系统提供的加载器。
    操作系统安装时设置活动分区会将该分区表项中的活动标记为0x80
    OBR(OS boot Record)存放在分区(主分区或者逻辑分区)最开始的扇区,引导扇区,前三个字节存放跳转指令,将处理器带入操作系统引导程序。
    OBR是从DBR(DOS boot Record)遗留下来的。
        DBR:跳转指令,从MBR跳转到引导代码;厂商信息,DOS版本信息;BIOS参数块BPB;操作系统引导程序;结束标识0x55,0xAA
    EBR(Expand Boot Record)为扩展分区而来,有多个。与MBR结构相同,位于子扩展分区最开始的扇区。

NASM

免费+语法简洁+支持Linux平台的汇编语言编译器
汇编语言在操作系统中:硬件访问、中断调用、端口读写、线程切换...
编译器给程序中各符号(变量名或函数名)分配的地址,就是各符号相对于文件开头的偏移量

secion

在程序中宣称一个区域。只是为了在逻辑上将程序划分成几个部分。

vstart

section用vstart修饰后,可以被赋予一个虚拟起始地址。
vstart=xxxx 和 org xxxx功能一样
时机:我预先知道我的程序被加载到某地址处。

CPU大致工作原理

控制单元:CPU控制中心,IR指令寄存器,ID指令译码器,OC操作控制单元
    根据IP寄存器指向将内存中的指令装载至IR->指令译码器按照指令格式解码->
    一般指令格式:前缀+操作码+寻址方式、操作数类型+立即数+偏移量
运算单元:
存储单元:CPU内部的L1、L2缓存寄存器;采用SRAM(static RAM),不需充电,性能强劲,但集成度低。

两类寄存器

程序员可以使用的,如通用寄存器,段寄存器。
程序员不可以使用的,如ALU算术逻辑单元求和时使用的数据暂存寄存器,GDTR、IDTR、LDTR、TR、CR0~3、IP、flags、DR0~7

寄存器

段寄存器:CS DS(数据段)、ES(附加段)、FS(附加段)、GS(附加段)、SS(堆栈段,在内存中) 32位CPU中16位宽
通用寄存器:AX BX CX DX SI DI BP SP
IP flags寄存器 实模式16位宽

保护模式特权级

CPL、DPL、RPL读写硬盘数据的例子

寄存器寻址方式

直接寻址:默认段基址是DS;如果使用段跨越前缀fs,段基址就是gs寄存器
基址寻址:bs或bp作为基址寄存器,bs+DS,bp+SS
略:待补充

外部中断

中断信号线:
    INTR:可屏蔽中断
    NMI:紧急中断,不可屏蔽
可屏蔽中断:
    可以通过eflags寄存器中的IF位将所有的外部设备中断屏蔽
不可屏蔽中断:中断号2

内部中断

int 8位立即数
int3 调试断点指令
调试过程: fork一个子进程;设置断点就是父进程修改子进程的指令,将其用int3指令替换(先备份),从而子进程调用int3指令触发中断。
into 中断溢出。触发的是中断向量号4,受标志寄存器eflags的影响
bound 检查数组索引是否越界,5号中断
ud2软件测试,无实际意义
有些内部中断会无视IF位
异常和不可屏蔽中断由CPU提供,外部设备的可屏蔽中断由中断代理提供(8259A),软中断由软件提供。

中断描述符表

实模式下也有中断,由中断向量表提供入口,4字节
中断描述符表:中断描述符|任务门描述符|陷阱门描述符 8字节
IDTR:中断描述符表寄存器,48位 12位表界限+32位表基址
描述符中的P位表示中断处理程序是否存在

中断处理过程

1
2
3
1. 中断向量号->中断门描述符 向量号*8+IDTR
2. 处理器进行特权级检查 CPL在门描述符DPL和门中目标代码DPL之间
3. 执行中断处理程序

-------------本文结束 感谢您的阅读-------------
作者GonewithGt
有问题请 留言 或者私信我的 微博
满分是10分的话,这篇文章你给几分