【Linux0.11代码分析】04 之 head.s 启动流程
【Linux0.11代码分析】04 之 head.s 启动流程
- 一、boot/head.s
系列文章如下:
系列文章汇总:《【Linux0.11代码分析】之 系列文章链接汇总(全)》
.
1.《【Linux0.11代码分析】01 之 代码目录分析》
2.《【Linux0.11代码分析】02 之 bootsect.s 启动流程》
3.《【Linux0.11代码分析】03 之 setup.s 启动流程》
4.《【Linux0.11代码分析】04 之 head.s 启动流程》
5.《【Linux0.11代码分析】05 之 kernel 初始化 init\main.c 代码分析》
6.《【Linux0.11代码分析】06 之 kernel 初始化 init 进程代码分析》
head.s 程序编译后会被连接成system模块的最前面开始部分,它处于内存绝对地址 0x00000处,
它主要功能为:
- 加载各个数据段寄存器,重新设置中断描述符表,共
256项,并使各个表项均指向一个只报错误的哑中断程序。 - 然后重新设置全局描述符表。
- 使用物理地址
0与1M开始处的内容相比较的方法,检测A20地址线是否真的开启
(如果没有开启,则在访问高于1Mb物理内存地址时CPU实际只会访问(IP MOD 1Mb)地址处的内容),
如果检测下来发现没有开启则进入死循环。 - 然后测试
PC机是否含有数学协处理器芯片,并在控制寄存器CR0中置相应的标志位 - 设置分页处理机制,将页目录表放在绝对物理地址
0开始处,紧随后面放置4个页表(可寻址16MB内存),并分别设置它们的表项 - 最后利用
ret返回指令将预先放置在堆栈中/init/main.c程序的地址弹出,去运行main()程序,同时它可以刷新预取指令队列。
一、boot/head.s
/* head.s 含有 32 位启动代码* 注意!!! 32 位启动代码是从绝对地址 0x00000000 开始的,* 这里也同样是页目录将存在的地方,因此这里的启动代码将被页目录覆盖掉 */
.text
.globl idt,gdt,pg_dir,tmp_floppy_area
pg_dir: // 页目录标识符
.globl startup_32
startup_32:movl $0x10,%eax // 32位寄存器 eax = 0x00000010mov %ax,%ds // 将ds = es = fs = gs = 0x10mov %ax,%esmov %ax,%fsmov %ax,%gslss stack_start,%esp // 设置系统堆栈, _stack_start : ss:espcall setup_idt // 设置中断描述符表=================>+ setup_idt:+ lea ignore_int,%edx+ movl $0x00080000,%eax+ movw %dx,%ax /* selector = 0x0008 = cs */+ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */+ + lea idt,%edi+ mov $256,%ecx+ rp_sidt:+ movl %eax,(%edi)+ movl %edx,4(%edi)+ addl $8,%edi+ dec %ecx+ jne rp_sidt+ lidt idt_descr+ ret<=================call setup_gdt // 设置全局描述符表=================>+ setup_gdt:+ lgdt gdt_descr+ ret<=================// 由于加载了 gdt,所以重部重装载所有的段寄存器movl $0x10,%eax # reload all the segment registersmov %ax,%ds # after changing gdt. CS was alreadymov %ax,%es # reloaded in 'setup_gdt'mov %ax,%fsmov %ax,%gslss stack_start,%esp // 设置系统堆栈, _stack_start : ss:espxorl %eax,%eax// 检查A20地址线是否已经开启,向内存地址0x000000处这与任意一个数值 ,然后看内存地址0x100000(1M)是否也是这个值,// 如果一直相同的话,说明A20地址线没有选通,结果内核不能使用1MB以上内存
1: incl %eax # check that A20 really IS enabledmovl %eax,0x000000 # loop forever if it isn'tcmpl %eax,0x100000je 1b// 于检查数学协处理器芯片是否存在修改控制寄存器 CR0,// 在假设存在协处理器的情况下执行一个协处理器指令,// 如果出错的话则说明协处理器芯片不存在,需要设置 CR0 中的协处理器仿真位 EM(位 2),并复位协处理器存在标志 MP(位 1)。movl %cr0,%eax # check math chipandl $0x80000011,%eax # Save PG,PE,ET
/* "orl $0x10020,%eax" here for 486 might be good */orl $2,%eax # set MPmovl %eax,%cr0call check_x87====================>+ // 下面 fninit 和 fstsw 是数学协处理器(80287/80387)的指令。+ // finit 向协处理器发出初始化命令,它会把协处理器置于一个未受以前操作影响的已知状态,设置+ // 其控制字为默认值、清除状态字和所有浮点栈式寄存器。非等待形式的这条指令(fninit)还会让+ // 协处理器终止执行当前正在执行的任何先前的算术操作。fstsw 指令取协处理器的状态字。如果系+ // 统中存在协处理器的话,那么在执行了 fninit 指令后其状态字低字节肯定为 0。+ check_x87:+ fninit // 向协处理器发出初始化命令+ fstsw %ax // 取协处理器状态字到 ax 寄存器中+ cmpb $0,%al // 初始化后状态字应该为 0,否则说明协处理器不存在+ je 1f /* no coprocessor: have to set bits */+ movl %cr0,%eax // 如果存在则向前跳转到标号 1 处,否则改写 cr0+ xorl $6,%eax /* reset MP, set EM */+ movl %eax,%cr0+ ret<====================jmp after_page_tables// 分别压栈: 0, 0, 0, L6的地址, main()的地址
after_page_tables:pushl $0 # These are the parameters to main :-)pushl $0pushl $0pushl $L6 # return address for main, if it decides to.pushl $mainjmp setup_paging
L6:jmp L6 # main should never return here, but# just in case, we know what happens./* Setup_paging通过设置控制寄存器cr0的标志(PG位31)来启动对内存的分页处理功能,* 并设置各个页表项的内容,以恒等映射前 16MB 的物理内存* 尽管所有的物理地址都应该由这个子程序进行恒等映射,但只有内核页面管理函数能直接使用>1Mb 的地址 * * 在内存物理地址 0x0 处开始存放 1 页页目录表和 4 页页表。页目录表是系统所有进程公用的,* 而这里的 4 页页表则属于内核专用,它们一一映射线性地址起始 16MB 空间范围到物理内存上。* 对于新的进程,系统会在主内存区为其申请页面存放页表。另外,1 页内存长度是 4096 字节。*/
.align 2 // 按 4 字节方式对齐内存地址边界
setup_paging: 首先对 5 页内存(1 页目录 + 4 页页表)清零movl $1024*5,%ecx /* 5 pages - pg_dir+4 page tables */xorl %eax,%eaxxorl %edi,%edi /* pg_dir is at 0x000 */cld;rep;stosl// 设置页目录表中的项,因为我们(内核)共有 4 个页表所以只需设置 4 项// 页目录项的结构与页表中项的结构一样,4 个字节为 1 项// 如"$pg0+7"表示:0x00001007,是页目录表中的第 1 项// 第 1 个页表的属性标志 = 0x00001007 & 0x00000fff = 0x07,表示该页存在、用户可读写。movl $pg0+7,pg_dir /* set present bit/user r/w */movl $pg1+7,pg_dir+4 /* --------- " " --------- */movl $pg2+7,pg_dir+8 /* --------- " " --------- */movl $pg3+7,pg_dir+12 /* --------- " " --------- */// 填写 4 个页表中所有项的内容,共有:4(页表)*1024(项/页表)=4096 项(0 - 0xfff),也即能映射物理内存 4096*4Kb = 16Mb// 每项的内容是:当前项所映射的物理内存地址 + 该页的标志(这里均为 7)// 使用的方法是从最后一个页表的最后一项开始按倒退顺序填写。// 一个页表的最后一项在页表中的位置是 1023*4 = 4092。因此最后一页的最后一项的位置就是$pg3+4092。movl $pg3+4092,%edimovl $0xfff007,%eax /* 16Mb - 4096 + 7 (r/w user,p) */std // 方向位置位,edi 值递减(4 字节)
1: stosl /* fill pages backwards - more efficient :-) */subl $0x1000,%eaxjge 1bxorl %eax,%eax /* pg_dir is at 0x0000 */ // 页目录表在 0x0000 处movl %eax,%cr3 /* cr3 - page directory start */ // 设置启动使用分页处理(cr0 的 PG 标志,位 31)movl %cr0,%eaxorl $0x80000000,%eax // 添上 PG 标志movl %eax,%cr0 /* set paging (PG) bit */// 在改变分页处理标志后要求使用转移指令刷新预取指令队列,这里用的是返回指令 ret。// 该返回指令的另一个作用是将堆栈中的 main 程序的地址弹出,并开始运行/init/main.c 程序。// 本程序到此真正结束了。 ret /* this also flushes prefetch-queue */.align 2
.word 0
idt_descr:.word 256*8-1 # idt contains 256 entries.long idt
.align 2
.word 0
gdt_descr:.word 256*8-1 # so does gdt (not that that's any.long gdt # magic number, but it works for me :^).align 8
idt: .fill 256,8,0 # idt is uninitializedgdt: .quad 0x0000000000000000 /* NULL descriptor */.quad 0x00c09a0000000fff /* 16Mb */.quad 0x00c0920000000fff /* 16Mb */.quad 0x0000000000000000 /* TEMPORARY - don't use */.fill 252,8,0 /* space for LDT's and TSS's etc */
相关文章:
【Linux0.11代码分析】04 之 head.s 启动流程
【Linux0.11代码分析】04 之 head.s 启动流程 一、boot/head.s 系列文章如下: 系列文章汇总:《【Linux0.11代码分析】之 系列文章链接汇总(全)》 . 1.《【Linux0.11代码分析】01 之 代码目录分析》 2.《【Linux0.11代码分析】02 之…...
自动化测试和selenium的使用
目录 自动化测试定义 为什么选择selenium来作为我们web自动化测试的工具? 自动化测试定位元素 使用cssSelector定位 使用XPath 定位 操作测试对象 模拟手动从键盘输入 点击对象 获取页面文本 清除对象输入的文本内容 添加等待(三种方式&#…...
Ubuntu常用终端操作
终端快捷键 打开 Ctrlaltt:打开终端(默认路径为家目录) Ctrlshiftn:打开终端(与当前终端处于同一路径下) Ctrlshiftt:打开终端(在大终端下面创建小终端) alt数字 关闭 exitCtrld 窗口切换 …...
Spring Security 6.x 系列【34】认证篇之前后端分离场景下的集成方案
有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 3.0.4 本系列Spring Security 版本 6.0.2 源码地址:https://gitee.com/pearl-organization/study-spring-security-demo 文章目录 1. 前言2. 案例演示2.1 未认证2.2 认证成功2.3 认证失败2.4 权限不足2.5 注…...
Qt之QTextToSpeech 让你的应用程序说话
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言QTextToSpeech基础使用1.创建一个QTextToSpeech对象2.朗读文字3.朗读文件和状态信息4.设置QTTS(QTextToSpeech)属性5.输出支持区域的设置列表、语言6.实现小数点朗读QTextToSpeech项目(练习)…...
为什么程序员喜欢用Linux?
Linux哪些行业在运用? Linux系统运用极其广泛,不少用户只知道windows,是因为,Linux的运用主要是在企业端。现在科技极其发达,我们手机在手,就能干很多事情,只需点一点屏幕,轻松完成…...
leetcode 598. 范围求和 II
题目描述解题思路执行结果 leetcode 598. 范围求和 II 题目描述 范围求和 II 给你一个 m x n 的矩阵 M ,初始化时所有的 0 和一个操作数组 op ,其中 ops[i] [ai, bi] 意味着当所有的 0 < x < ai 和 0 < y < bi 时, M[x][y] 应该…...
javaweb前置知识
1.CSS CSS的角色:页面显示的美观风格CSS的基础语法:标签样式;类样式;ID样式;组合样式;嵌入式样式表;内部样式表;外部样式表盒子模型:border、margin、padding定位和浮动…...
基于微信小程序的酒店预定管理系统设计与实现
第1章 绪论 1 1.1开发背景与意义 1 1.2开发方法 1 1.3论文结构 1 2系统开发技术与环境 3 2.1 系统开发语言 3 2.2 系统开发工具 3 2.3 系统页面技术 3 2.4 系统数据库的选择 4 2.5 系统的运行环境 4 2.5.1 硬件环境 4 2.5.2 软件环境 4 3系统分析 5 3.1可行性分析 5 3.1.1 经济…...
26. Service——深入学习
本章讲解知识点 Service 会话保持机制Service 的多端口设置Service 支持的网络协议Kubernetes 的服务发现机制Headless ServiceEndpoint Slices这一节我们来讲讲 Service 更多细节 1. Service 会话保持机制 Service 支持通过设置 sessionAffinity 实现基于客户端 IP 的会话保…...
【算法】Check If Word Is Valid After Substitutions 检查替换后的词是否有效
文章目录 Check If Word Is Valid After Substitutions 检查替换后的词是否有效问题描述:分析代码 Tag Check If Word Is Valid After Substitutions 检查替换后的词是否有效 问题描述: 给你一个字符串 s ,请你判断它是否 有效 。 字符串 s…...
基于jenkinsfile布置java工程
需求 通过jenkins发布java项目到服务器 预备环境 项目地址: https://gitee.com/asaland/sb-docker-appJenkins 2.387.3 通过Jenkinsfile实现方式 jenkins ui 配置pipeline 什么是pipeline? 直接看注释吧,简单点就是编排可以多个跨时间的构建代理…...
Spring JpaTransactionManager事务管理
首先,在做关于JpaTransactionManager之前,先对Jpa做一个简单的了解,他毕竟不如hibernate那么热门,其实二者很相识,只不过后期hibernate和JDO 版本都已经兼容了其Jpa,目前大家用的少了。 JPA全称Java Persi…...
全国职业院校技能大赛网络建设与运维赛项赛题(七)
全国职业院校技能大赛 网络建设与运维 赛题 (七)...
asp.net+sqlserver企业公司进销存管理系统
基于WEB的进销存管理系统主要企业内部提供服务,系统分为管理员,和员工2部分。 在本基于WEB的进销存管理系统中分为管理员,和普通用户2中模式,其中管理人员主要是对企业内商品类型。商品信息商品的出入库信息,以及员工…...
WxGL应用实例:绘制点云
WxGL附带了几个工具函数,其中read_pcfile用来解析.ply和.pcd格式的点云文件,该函数返回一个PointCloudData类实例,包含以下属性: PointCloudData.ok - 数据是否可用,布尔型PointCloudData.info - 数据可用性说明&…...
一个月内面了30家公司,薪资从18K变成28K,真行啊····
工作3年,换了好几份工作(行业流行性大),每次工作都是裸辞。朋友都觉得不可思议。因为我一直对自己很有信心,而且特别不喜欢请假面试,对自己负责也对公司负责。 但是这次没想到市场环境非常不好,…...
《计算机网络——自顶向下方法》精炼——1.4到1.7
三更灯火五更鸡,努力学习永不止。无惧困难与挑战,砥砺前行向成功。 文章目录 引言正文时延排队时延 吞吐量协议层次,服务模型(重点)封装(重点)网络安全(选看)恶意软件的分…...
消息队列 (Message Queue)
消息队列 What 消息队列 是消息的队列;是消息的临时缓冲;是发布/订阅模式的兄弟;在多个进程/线程间实现异步通讯模式。 Why 消息队列在多个进程/线程中实现了异步通讯模式。 这里我们先介绍下同步消息处理。对于同步消息处理࿰…...
JavaScript原型链污染学习记录
1.JS原型和继承机制 0> 原型及其搜索机制 NodeJS原型机制,比较官方的定义: 我们创建的每个函数都有一个 prototype(原型)属性,这个属性是一个指针,指向一个对象, 而这个对象的用途是包含可…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...
基于鸿蒙(HarmonyOS5)的打车小程序
1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...
