操作系统篇
文章平均质量分 58
从零搭建系统
Linux老A
嵌入式打杂专家
展开
-
X86系统中断处理与特权级转移 软中断实现系统调用 用户态程序使用软中断扎内核调用内核态程序
不会,中断整体是由 处理器 与 8259A中断控制器 共同管理的,虽然8259A可以不停的将中断请求发送给处理器,但是处理器有屏蔽中断的开关,只要当前中断处理还没有完成,就可以将IF置0 即不接受其他中断请求。处理器没有中断优先级的概念,它只有响应与不响应的概念,当在执行中断处理时,屏蔽外部中断请求时 不响应8259A发来的中断请求。相反 当中断服务程序完成时,重新开始响应8259A的中断请求。处理器拿到中断向量之后,就会到中断描述符表中查找对应的中断向量,进而找到一个中断描述符,然后继续特.原创 2022-01-29 20:58:04 · 2310 阅读 · 1 评论 -
X86系统中断代理8259A 说明与控制
学习自唐佐林老师问题:不同外设如何向处理器发送中断信号?当多个外设同时产生中断时,处理怎么处理?我们想象中的 外设与CPU的连接方式大致是这样:然而 真实的情况并非如此,真是的情况 是 CPU 将外设的中断的管理交给了8259A控制器 ,CPU 只做中断处理,如下图:对于处理器而言 只有一个中断引脚,也就是说 只能有一个8259A直接连接到处理器的中断引脚上面。下图的 从8259A接到了 主8259A的 IR2,所以当 从8259A 有多个中断时,就需要设定优先级,所以原创 2022-01-29 14:03:09 · 1105 阅读 · 0 评论 -
x86系统的中断机制
提炼:1 中断基本概念 (外部中断 内存中断,以及区别)2 实模式下 与 保护模式下 中断响应过程 以及 中断与对应的中断服务程序 如何映射关联外部中断:外部设备向处理器发出的中断,如网卡 键盘 鼠标等等内部中断:处理器自己所发出的中断软中断:由代码来产生,在形式上 类似于函数调用异常:处理器是逐条指令执行的 如果遇到不认识 不合法的指令 就会发出异常中断 很形象的比喻:INTR 可屏蔽中断NMI 不可屏蔽中断不论工作在什么模式(实模式,保护模式),处理器和原创 2022-01-15 23:21:36 · 1791 阅读 · 1 评论 -
X86系统内存分页机制--加载不同的页表并读取同一个虚拟地址中内容 或者 调用同一个虚拟地址的函数
实验1 :加载不同的页表并读取同一个虚拟地址中内容%include "inc.asm";两个页目录 子页表 起始地址 对应两个不同的任务;简单的分页构建方法,所有的子页表顺序的连续排列;注意: 因为我们设计的也表示连续的内存排布,所以单个任务的页表总大小就是 :1024(页表个数)*4096(单个子页表大小) ;所以 设计多个页表的时候 需要注意 每个页表的基地址之间的差值 要大于页表总大小;页目录0起始地址PageDirBase0 equ 0x200000;子页表0..原创 2022-01-15 13:31:30 · 375 阅读 · 0 评论 -
X86系统内存分页机制--将同一个虚拟地址映射到不同的物理地址 并反编译验证
实验 : 将同一个虚拟地址映射到不同的物理地址说明:此处所讲的 <将同一个虚拟地址映射到不同的物理地址> 是指 将 同一个虚拟地址 在不同的页表中进行映射,并直接指定映射的物理地址,此处直接指定的物理地址 依然是某个物理页的起始地址,特点式目标物理地址 低12位为0,即目标物理地址是4K的整数倍 说明是某个物理页面(一页4K大小)的起始地址。所以最终的映射方式不变,依然是虚拟地址高10位 作为 子页表在页目录的位置,中间10位是 目标物理页号地址 在子页表中的位置,最后低12位是 ...原创 2022-01-10 23:28:10 · 805 阅读 · 0 评论 -
X86系统上的内存分页机制 --页表映射 与 切换页表
操作系统里面的每一个任务都有自己独立使用的页表,当操作系统切换任务来执行的时候,也要对应的切换页表,另外每一个任务都有自己独立的虚拟地址空间,而每个任务 虚拟地址空间中数据的分布肯定是不一样的,因此会出现这样的情况:同一个虚拟地址 在不同的页表的映射下 ,被转换成了不同的物理地址。切换页表实验%include "inc.asm";两个页目录 子页表 起始地址 对应两个不同的任务;简单的分页构建方法,所有的子页表顺序的连续排列;页目录起始地址PageDirBase0 equ .原创 2022-01-08 07:52:00 · 937 阅读 · 0 评论 -
X86系统上的内存分页机制
因为 所有的物理页的起始地址都必须是按照4K字节来对齐的,也就是被4096除尽,从二进制角度来看 就是低12位全为0,也就是说 不论在页目录中(存储子页表物理地址) 还是页表中(存储目标数据物理地址),所存储的那些物理页的起始地址低12位都是0。所以低12位就没必要作为地址位了 所以用于存储属性。实验:x86处理器 设置页目录 设置子页表 启用处理器分页机制开启分页机制后,效果就是:当我们访问一个地址的时候,就会通过页映射得到实际的物理地址了。inc.asm; Segme...原创 2022-01-03 17:32:53 · 485 阅读 · 0 评论 -
页式内存管理 -- 任务与页表的关系,页框表,页置换原理,单级页表与二级页表
问题:原创 2022-01-02 15:59:11 · 329 阅读 · 0 评论 -
页式内存管理 --引入页式内存 并引申出虚拟内存空间与物理内存空间,以及他们的映射逻辑,页请求,页交换
回顾:保护模式是用来保护内存段的,在X86系列的处理器中内置了保护模式,开启保护模式后,某段内存的访问就是受限的,即受保护。而这里所说的某段内存 就是内存段,就是一段连续的内存空间,即保护模式用来保护一段连续的内存空间。我们将这 一段连续的内存空间 简称为段。X86系列的处理器最典型的特色就是 段式内存管理。不论访问哪一段内存空间,不论是实模式下 还是保护模式下,终究都是需要 段寄存器中的值 加上 一个段内偏移地址 才能得到具体的内存地址。C语言里面的数组就是 段式内存管理的纯软原创 2022-01-01 21:45:13 · 540 阅读 · 0 评论 -
特权级转移 之 深入理解 调用门升特权级 与 retf远返回降特权级
注意 jmp 用于有去无回的跳转,跳转后不会返回思考 :为什么 jmp指令特配调用门 只做同级跳转。具体的原因就是 jmp 用于有去无回的跳转,跳转后不会返回,如果用jmp 跳转到高特权级代码段,就会一直执行下去 不会返回,这样特权级设置的就没有意义了,会导致安全性问题,所以 这样做是为了内核安全。jmp 指令是有去无回的跳转,不会在栈中留下返回信息。关于2:如果不对相关段寄存器做清零,那么从高特权级 返回到 低特权级后,低特权级代码段就可以访问高特权级的数据,这是不原创 2021-12-30 07:51:19 · 544 阅读 · 0 评论 -
特权级转移 之 保护模式下代码段(一致性代码段 非一致性代码段)特权级保护依据
提炼:可以 不使用 调用门(低特权级跳转到高特权级) 和 TSS任务状态段(高特权级跳转到低特权级) 的情况下 做代码段之间的跳转(特权级切换),所使用的就是保护模式下对于代码段特权级保护的依据,即 一致性代码段 与 非一致性代码段的规则。1 对于非一致性代码段,只能同级转移其他同特权级代码段(不限一致或非一致) -----跳转到—> 当前非一致性代码段2 对于一致性代码段,支持低特权级到高特权级一致性代码段的转移,但是!!! 但是转移之后 CPL不变!!!正常通过调用门跳原创 2021-12-25 17:24:40 · 543 阅读 · 0 评论 -
特权级转移 之 保护模式下数据段特权级保护依据
提炼:1 对于数据段 ,处理器进行特权级检查的时机 就是为段寄存器赋值的那一个时刻在保护模式下 当处理器对段寄存器进行赋值的时候,处理器就会使用规则进行特权级的检查。如:mov ax, Data32Selectormov ds, ax2 数据段的特权级保护规则就是CPL <= DPL && RPL <= DPL,即代码段特权级 与 数据段选择子请求特权级RPL 都要高于或等于 DPL特权级3 对于栈段,当为SS寄存器赋值的时候,使用规则 :(CP原创 2021-12-25 17:03:48 · 2525 阅读 · 0 评论 -
特权级转移之 高,低特权级互相转移,模拟操作系统内核态与用户态切换以及应用程序调用系统资源
TSS中保存的栈信息,是在特权级转移的时候被用到,具体就是在从低特权级转移到高特权级的时候会用。注意 从低到高问题:为什么要保存 段寄存器值和通用寄存器的值?既然是为了实现多任务,那么任务之间显然要进行切换,切换任务的时候需要保存当前任务上下文,那么什么是任务上下文? 具体就是任务执行时的关键寄存器的值,包括段寄存器和通用寄存器的值。把这些寄存器值保存之后,等任务切换回来的时候,直接把这些寄存器值恢复 任务的执行状态就恢复了。TSS这个数据结构中很大一部分就是保存了寄存器的值的。原创 2021-12-19 21:00:47 · 1320 阅读 · 1 评论 -
保护模式中的特权级 之 从高特权级代码段 跳转到 低特权级代码段
return指令本质上是一个跳转指令,是用来做跳转的,而不是我们根深蒂固所理解的返回,只不过说,它最常用的场景是用于函数返回。用于做跳转 和 call 成对的出现首先将 ax寄存器值 bx寄存器值 压入栈中,然后通过远调用指令(通过选择子+偏移地址)调用函数,调用的函数在另一个段中,因此是远调用。调用函数时,栈的变化和之前学习的一样,原理不变,就是讲当前地址压入栈中,但是细节上,当前地址变成了两个:第一个是段地址,其实就是选择子,当前所执行的代码段的选择子是放到原创 2021-11-02 22:30:58 · 391 阅读 · 0 评论 -
保护模式中的特权级 之 使用调用门描述符实现段间跳转
问题:如何在不同特权级的代码之间跳转执行?门描述符也是描述符,结构上同 段描述符一样,也是占用8个字节。调用门描述符: 调用门中保存了 某个段的选择子以及相应的偏移地址。 地址位一共32位 4个字节,正好是一个偏移地址所需要存储空间。调用门描述符的工作原理:只要是描述符,那么必然会对应有一个选择子,既然调用门描述符是一个描述符,那么就会对应一个选择子,即调用门选择子。可以使用 调用门选择子 来访问对应的门描述符, 门描述符中有两个很重要的信息,一个是选择子,原创 2021-10-31 11:20:16 · 396 阅读 · 0 评论 -
保护模式中的特权级简述
可写属性 : 栈段的标志可读属性:数据段的标志问题:保护模式处理利用段界限对内存访问进行保护之外,是否还提供其他的保护机制?现实产品中特权级的分配更加简单,如 Linux和Windows ,特权级只有两种,0 和 3,要么是内核,要么是应用程序,也就是我们常听到的 内核态和用户态。应用程序运行在用户态,特权级为3,内核程序运行在内核态 特权级为0X86处理器这样设计的原因是为了安全 ,如果一个应用程序想做破坏,他可以破坏系统,直接将操作系统内核的相关段全原创 2021-10-31 11:09:46 · 231 阅读 · 0 评论 -
局部段描述符表的使用
我们在保护模式下的编程有一个特点,就是定义众多的段(section),而这些段的功能是不一样的,比如 有可执行的代码段,数据段,栈段等等,我们通过定义众多这样的段,来进行保护模式下的编程。但是 如果我们的代码量急剧的膨胀,代码中需要定义几百上千个段,而每个段又需要在全局段描述附表GDT中有对应的描项,那这样的话 全局段描述符表会不够用, 全局段描述符表也是有界限的!所以全局段描述附表 是不能够无限制的增加描述项的。所以可以用 局部段描述符表 进行分级管理,每一个局部段描原创 2021-10-26 08:01:37 · 277 阅读 · 0 评论 -
从保护模式返回实模式
杂记:1 为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址:CS(Code Segment):代码段寄存器;DS(Data Segment):数据段寄存器;SS(Stack Segment):堆栈段寄存器;ES(Extra Segment):附加段寄存器。杂记2: jmp段内跳转和段间跳转函数调用必须要有栈空间的存在,除了栈空间之外,还要一个栈顶指针,也就是 esp 寄存器,它必须指向栈空间最顶上的位置。先从 32位保护模式的代码原创 2021-10-19 22:47:52 · 573 阅读 · 0 评论 -
80386保护模式下实现 Hello World
利用选择子 拿到对应的段描述符,之后自然就可以拿到段基址,再加上段内偏移地址,就可以跳转dword 双字 32位word 两个字节 16位dword 四个字节 32位问题:为什么要明确的标识出 dword 32位呢?答案:因为我们现在的无条件跳转 jmp 是从16位代码段 跳转到 32位代码段,16位代码段的意思就是 编译器在默认的情况下 对16位代码段里面的立即数 解释为16位。编译器有默认的准则,如果不明确指定,则在16位代码段中,编译器会默认 认为这个立即数就是16位的原创 2021-10-12 23:29:15 · 425 阅读 · 0 评论 -
80286 与 80386,实模式与保护模式切换编程
学习自 狄泰软件1 EAX与AX不是独立的,EAX是32位的寄存器,而AX是EAX的低16位。2 or 对两个操作数进行逻辑(按位)或操作80286 虽然有了保护模式,但其依然是 16 位的 CPU ,其通用寄存器还是 16 位宽,但其与 8086 不同的是其地址线由 20 位变为了 24 位,即寻址空间变成了 24 次方,等于 16MB 大小。虽然80286可以将地址线变成了24位,可以访问16MB的内存,但是其用来寻址的通用寄存器还是16位的,也没有突破一个寄存器只能访问64kb空间的限制,如原创 2021-10-10 23:25:13 · 1037 阅读 · 0 评论 -
实模式8086 与 保护模式80286
学习自 狄泰软件1MB=1024KB2(20) = 1 048 576 => 1M2(16) = 65536 => 60K2(32) = 4,294,967,296 => 4,294M => 4G如 将一段内存定义为 只存放 指令,不放数据,于是这一段只放指令的内存 就叫做代码段。而 这些指令所需要的数据 放到另一块内存,这段内存就叫数据段。所以 代码段 数据段等概念 是诞生于8086处理器时代 !!! 当今处理器的鼻祖。mov ax, [0x12原创 2021-10-10 23:07:49 · 395 阅读 · 0 评论 -
主引导程序控制权的转移,彻底突破512字节限制
学习自 狄泰软件Stack 空间 是栈空间,用于函数调用0x7c00 : 主引导程序的起始地址0x7e00 – 0x9000 : 是FAT 表,占据4KB 空间0x9000 : 我们需要将目标程序(Loader程序)加载到 0x9000地址处,我们最终将控制权从 主引导程序(Boot程序)里面 跳转到 0x9000处,开始向后执行,也就是将控制权从Boot程序 转交给 Loader程序。1 用bx寄存器 拿到 FAT表的起始地址2 拿到目标文件的 文件目录项起始地址拿到目标文件的 所原创 2021-10-05 14:50:12 · 543 阅读 · 0 评论 -
文件系统FAT表查询,读取
学习自狄泰软件1 CX DX寄存器是16位的 分别用 ch dh cl dl 代表高低八位数据2 $ 表示当前指令行地址,$$表示当前汇编段起始地址3 cmp si di如果 si > di 走 ja如果 si<=ji 走jna如果 si < di 走 jb如果 si >= di 走 jnb4 mul 乘法,被乘数放在 AL 寄存器,乘数放到通用寄存器或内存,结果放在AX寄存器5 and 按位与6 shl 左移7 shr 右移8 拷贝操作注意 空间重叠原创 2021-10-04 18:42:37 · 2669 阅读 · 0 评论 -
在文件系统的根目录区查找目标文件
学习自狄泰软件回忆前面的知识,我们知道 文件系统中存在根目录区,根目录区由目录项组成,每个目录项代表根目录中的一个文件索引所以我们可以根据目录项的前 11 个字节判断文件属性(名字等等),具体方法就是逐个比较这11个字节的空间,内存比较[si] 将si 寄存器中存储的 地址所代表的空间出 取一个字节数据[di] 同理...原创 2021-10-04 12:34:01 · 768 阅读 · 0 评论 -
在主引导程序中打印字符串,读取软盘数据
随记:1 在汇编中可以定义函数,函数名使用标签定义, 函数体最后一条指令是 ret, 调用函数 是call function2 如果代码中定义了函数,那么需要定义栈空间。用于保存关键寄存器的值,栈顶地址通过sp寄存器保存3 汇编中用 equ 定义常量,如 Const equ 0x7c00 == #define Const 0x7c00 .4 dx(db,dw,dd) 可以定义变量 他们与 equ的差别在于,equ定义不会占用内存空间,而dx定义占用对应的内存空间5 汇编中的16位除法操作原创 2021-09-26 22:31:30 · 292 阅读 · 0 评论 -
主引导程序 需要依赖 文件系统
学习自狄泰软件引子:主引导程序工作中有一项是 从存储介质中加载程序到内存。那么问题来了 主引导程序该怎么加载存储介质中的其他程序呢?注意 此时是没有操作系统的,直接用汇编写代码的条件下是不能直接指定文件名读取文件的!!! 所以 这就需要依赖文件系统了,说白了 文件系统就是文件数据的组织方式,只要知道了文件数据在存储介质中的组织方式,即只要知道了文件数据所在存储介质的 文件系统,就可以根据该文件系统的数据组织方式 访问存储介质,获得我们需要的文件数据。这就是 主引导程序需要依赖文件系统的原因。主引导程原创 2021-09-25 23:16:15 · 242 阅读 · 0 评论 -
关于BIOS 和 主引导程序 的一点随笔
学习自狄泰软件注意:BIOS 不是软件(Software),而是固件(Firmware) 固件是固化于硬件中的程序,在硬件出厂前已经烧写固定的。问题 BIOS 是怎么被运行起来的?问题:BIOS怎么在存储介质中寻找 主引导程序?BIOS怎么判断引导区有没有 主引导程序?...原创 2021-09-25 22:40:50 · 362 阅读 · 0 评论 -
15 ABI规范 栈帧结构,帧栈的形成过程
EIP 指令寄存器,其指向处理器下一条要执行的指令在内存的位置ESP 栈指针寄存器EBP 栈帧基地址寄存器也就是说每一个函数所需要的栈帧,即每一个函数所对应活动记录的大小是固定的,由编译器在编译的时候指定。编译器在编译的时候就确定了当前函数所需要的栈空间的大小了。 最终表现为汇编代码中第一个字面常量。函数结束的时候:move ebp, esp1 先将 ebp寄存器的值 赋值给 esp寄存器pop ebp2 此时pop 弹出来的值是 上一个栈帧的基准地址,pop到EBP寄存器中,此时原创 2021-07-25 21:59:03 · 505 阅读 · 0 评论 -
10 链接器--定制链接脚本 配合使用系统服务 设计体积受限的可执行程序
学习自唐佐林老师,仅作为个人笔记方向:如何设计一个体积受限的可执行程序,内容只有打印一行字符串解决思路:怎样做到体积最小?1 独立于 libc 库进行编译链接2 独立于 其他 一些无关的或者说仅仅使用了一点点部分的第三方库总之尽量减少使用其他的库所以需要自己定义链接脚本,因为既然独立于 libc库,也就是说需要自己指定入口函数了,不再使用默认的_start 入口函数了3 不依赖 libc 库的 printf(),自己直接使用内嵌汇编调用系统服务进行字符串打印!!链接脚本 只留原创 2021-07-25 12:14:15 · 158 阅读 · 0 评论 -
9 内嵌汇编,可以直接调用系统服务
学习自唐佐林老师,仅作为个人笔记注意 占位符的作用:当使用如 “r” 等限制符的时候,表示编译器会自动完成寄存器的分配。那么怎么引用这些被编译器自动分配的寄存器呢? 就是通过 %N 的形式加以引用,N可以是从0 到 9,N指示了寄存器在 “输出寄存器”和“输入寄存器” 列表中的索引#include <stdio.h>int main(){ int result = 0; int input = 1; int a = 1; int b原创 2021-07-24 15:34:53 · 252 阅读 · 0 评论 -
8 链接器 自定义链接脚本,指定入口函数,指定代码段起始地址等等
本文学习自狄泰软件学院 唐佐林老师的 操作系统课程,本文图片来源于唐佐林老师课程PPT,只用于个人笔记学习1 链接脚本的概念和意义2 链接脚本的本质3 链接脚本的写法和注意事项4 实验1 : 自定义的链接脚本中自己指定的 代码段和数据段的地址没有遵循linux平台对应用程序的规定5 实验2 :链接脚本中指定全局变量地址6 实验3 :在链接脚本中定义标识符,并且在源码中使用7 M...原创 2019-12-07 16:53:49 · 3077 阅读 · 2 评论 -
7 链接器 整合目标文件和库 为可执行程序,代码段的起始地址
本文学习自狄泰软件学院 唐佐林老师的 操作系统课程,本文图片来源于唐佐林老师课程PPT,只用于个人笔记学习1 链接器的意义2 链接器的工作内容3 main()函数是第一个被调用执行的函数吗?4 自定义程序入口函数目标文件是链接器的工作目标对象所以目标文件中各个段没有起始地址,各个标识符也没有自己实际地址,所以目标文件是不可以被执行的。段和标识符的实际地址需要链接器具体确...原创 2019-12-07 15:22:57 · 624 阅读 · 0 评论 -
操作系统前传第六课--开发中的辅助工具
本文学习自狄泰软件学院 唐佐林老师的 操作系统课程,本文图片来源于唐佐林老师课程PPT,只用于个人笔记学习测试程序func.c#include <stdio.h>int* g_pointer;void func(){ *g_pointer = (int)"D.T.Software"; return;}test.c#include <s...原创 2019-12-03 10:26:19 · 273 阅读 · 0 评论 -
操作系统前传第四课--深入浅出处理器之缓存
本文学习自狄泰软件学院 唐佐林老师的 操作系统课程,另外本文图片全部来源于唐佐林老师课程PPT,只用于个人笔记学习一 为什么需要缓存处理器处理的数据的速度非常快,但是他要从内存里面获取数据是很慢的,也就是说他读取数据的速度是很慢的,这样不能完全发挥处理器的能力。有人说用生产处理器的工艺去生产内存,这样理论是可以的,但是经济上不合理,成本是非常巨大的。解决方案:生产一个容量小一点,但是工...原创 2019-11-19 23:39:39 · 240 阅读 · 0 评论 -
操作系统前传第三课--深入浅出处理器之虚拟内存
本文学习自狄泰软件学院 唐佐林老师的 操作系统课程,另外本文图片全部来源于唐佐林老师课程PPT,只用于个人笔记学习目录:一 虚拟内存1 从现象引入虚拟内存2 虚拟内存的由来3 虚拟内存的意义以及虚拟内存的映射机制二 内存保护一 虚拟内存1 从现象引入虚拟内存system(“pause”); 暂定执行,暂定到我们在键盘上按下一个值为止。假若我们这个程序编译好了,编译出可...原创 2019-11-14 00:41:35 · 605 阅读 · 0 评论 -
操作系统前传第二课--深入浅出处理器之中断
本文学习自狄泰软件学院 唐佐林老师的 操作系统课程,另外本文图片全部来源于唐佐林老师课程PPT,只用于个人笔记学习从前都是接触硬件中断,今天看了唐sir的处理器中断篇,从软件角度了解了一下中断,即软中断!我们设置断点的需求就是要求程序执行之后停在指定的代码行,根据编译原理,我们知道,C程序在编译之后就是处理器的看得懂的指令了,因此每一个代码行都应该对应一个地址,每一个源程序的代码行都...原创 2019-11-12 00:20:18 · 362 阅读 · 0 评论 -
操作系统前传第五课/嵌入式C语言编译器
本文学习自狄泰软件学院 唐佐林老师的 操作系统课程,另外本文PPT全部来源于唐佐林老师课程PPT,只用于个人笔记学习目录:1 GCC与gcc2 交叉编译3 C语言编译器4 多语言混合开发方式5 gcc关键编译选项我们平时所说的编译器,其实包含了这几个部分,广义上的编译器包含了如上四个部分,其中的编译器部分是我们所说的狭义的编译器。我们要分清广义编译器和狭义编译器。...原创 2019-11-09 20:29:34 · 395 阅读 · 0 评论