Linux-0.11 boot目录head.s详解
Linux-0.11 boot目录head.s详解
模块简介
在head.s中,操作系统主要做了如下几件事:
- 重新设置中断描述符和全局描述符
- 检查A20地址线是否开启
- 检查数学协处理器
- 初始化页表并开启分页
- 跳转到main函数执行
过程详解
重新设置IDT和GDT
在setup.s中我们已经设置过了IDT和GDT, 为什么还要再设置一遍?
因为setup.s中设置的IDT和GDT后面会被覆盖,因此在head.S中会重新设置一遍。
startup_32:movl $0x10,%eaxmov %ax,%dsmov %ax,%esmov %ax,%fsmov %ax,%gslss stack_start,%espcall setup_idt !设置中断call setup_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
中断门描述符的格式如下所示:

检查A20地址线是否开启
下面用于检测A20地址线是否已经开启。
xorl %eax,%eax
1: incl %eax # check that A20 really IS enabledmovl %eax,0x000000 # loop forever if it isn'tcmpl %eax,0x100000je 1b
检查数学协处理器
下面用于检查数学协处理器芯片是否存在
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_x87jmp after_page_tables/** We depend on ET to be correct. This checks for 287/387.*/
check_x87:fninit !向协处理发出初始化命令fstsw %ax !取协处理器状态字到ax寄存器中cmpb $0,%alje 1f /* no coprocessor: have to set bits */movl %cr0,%eaxxorl $6,%eax /* reset MP, set EM */movl %eax,%cr0ret
初始化页表并开启分页
下面这里将进行页表的安装,安装的过程参考下面这张图:

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_pagingsetup_paging:movl $1024*5,%ecx /* 5 pages - pg_dir+4 page tables */xorl %eax,%eaxxorl %edi,%edi /* pg_dir is at 0x000 */cld;rep;stoslmovl $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 /* --------- " " --------- */movl $pg3+4092,%edimovl $0xfff007,%eax /* 16Mb - 4096 + 7 (r/w user,p) */std
1: stosl /* fill pages backwards - more efficient :-) */subl $0x1000,%eaxjge 1bcldxorl %eax,%eax !设置页目录表基址寄存器cr3的值movl %eax,%cr3 movl %cr0,%eax !设置启动使用分页处理orl $0x80000000,%eaxmovl %eax,%cr0 /* set paging (PG) bit */ret /* this also flushes prefetch-queue */
跳转到main函数执行
在setup_paging执行完毕之后,会通过ret返回,ret指令会将栈顶的内容弹出到PC指针中去执行。此时esp指向的位置存放的是main函数的地址。因此接下来会执行main函数。
注意到在将main入栈时,还一同入栈了一些其他参数
pushl $0 # These are the parameters to main :-)pushl $0pushl $0pushl $L6
这里就需要回顾一下c语言的调用规约,如下图所示:

因此这里可以得到L6是main函数的返回值。立即数0,0,0将会被作为main函数的入参。
接下来再看下面的代码就很清晰了,实际就是在建立好页表的映射关系后,就开始跳转到main函数去执行了(init/main.c)。
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_pagingsetup_paging:...ret
Q & A
setup_paging在建立页表时会将head.s的部分代码覆盖,怎么保证不会把正在执行的代码覆盖?
可以通过反汇编查看一下system模块的内存分布
objdump -d tools/system
如下所示:
00000000 <pg_dir>:0: b8 10 00 00 00 mov $0x10,%eax5: 8e d8 mov %eax,%ds...
0000005a <check_x87>:5a: db e3 fninit 5c: 9b df e0 fstsw %ax5f: 3c 00 cmp $0x0,%al...
00000071 <setup_idt>:71: 8d 15 28 54 00 00 lea 0x5428,%edx77: b8 00 00 08 00 mov $0x80000,%eax...
0000008e <rp_sidt>:8e: 89 07 mov %eax,(%edi)90: 89 57 04 mov %edx,0x4(%edi)...
000000a1 <setup_gdt>:a1: 0f 01 15 b2 54 00 00 lgdtl 0x54b2a8: c3 ret ...
00001000 <pg0>:...00002000 <pg1>:...00003000 <pg2>:...00004000 <pg3>:...
00005000 <tmp_floppy_area>:...
00005400 <after_page_tables>:5400: 6a 00 push $0x05402: 6a 00 push $0x0...
00005412 <L6>:5412: eb fe jmp 5412 <L6>
00005414 <int_msg>:5414: 55 push %ebp5415: 6e outsb %ds:(%esi),(%dx)...
00005428 <ignore_int>:5428: 50 push %eax5429: 51 push %ecx...
0000544e <setup_paging>:544e: b9 00 14 00 00 mov $0x1400,%ecx5453: 31 c0 xor %eax,%eax5455: 31 ff xor ...
000054aa <idt_descr>:54aa: ff 07 incl (%edi)54ac: b8 54 00 00 00 mov $0x54,%eax...000054b2 <gdt_descr>:54b2: ff 07 incl (%edi)54b4: b8 .byte 0xb854b5: 5c pop %esp...000054b8 <idt>:...00005cb8 <gdt>:...5cc0: ff 0f decl (%edi)
可以看到代码标号setup_page的起始地址是0000544e,而内存页表和页目录表的地址范围是0x0000-0x5000。因此当程序执行到setup_page时,将建立页目录表和页表, 这将会覆盖0x0000-0x5000的部分代码,即pg_dir,check_x87,setup_idt,rp_sidt,setup_gdt, 并不会覆盖到setup_page的代码,head.s在代码的分布计算上确实是费了一番功夫。
文中如有表达不正确之处,欢迎大家与我交流

相关文章:
Linux-0.11 boot目录head.s详解
Linux-0.11 boot目录head.s详解 模块简介 在head.s中,操作系统主要做了如下几件事: 重新设置中断描述符和全局描述符检查A20地址线是否开启检查数学协处理器初始化页表并开启分页跳转到main函数执行 过程详解 重新设置IDT和GDT 在setup.s中我们已经…...
离散数学_十章-图 ( 3 ):由旧图构造新图
📷10.3 由旧图构造新图 概念1. 子图2. 真子图3. 导出的子图 旧图构造新图的方法1. 删除或增加图中的边2. 边的收缩3. 删除顶点 有时解决问题只需要图的一部分。 比如我们现在只关心大型计算机网络中涉及济南,广州,深圳的计算机中心࿰…...
Golang每日一练(leetDay0083) 汇总区间、多数元素II
目录 228. 汇总区间 Summary Ranges 🌟 229. 多数元素 II Majority Element ii 🌟🌟 🌟 每日一练刷题专栏 🌟 Rust每日一练 专栏 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专…...
JAVA数组基础
目录 一、使用方式 1-动态初始化 ①先声明数组 ② 创建数组 ③分配方式 二、使用方式 2-静态初始化(直接在声明的同时初始化{ } ) 三、数组使用注意事项和细节 四、数组两种初始化方式都是将内存空间分配到堆上面的 一、使用方式 1-动态初始化 …...
Linux-0.11 文件系统exec.c详解
Linux-0.11 文件系统exec.c详解 模块简介 该模块实现了二进制可执行文件和shell脚本文件的加载和执行。 函数详解 create_tables static unsigned long * create_tables(char * p,int argc,int envc)该函数的作用是建立参数和环境变量指针表。 create_table的作用就是建立…...
NET框架程序设计-第1章.NET框架开发平台体系架构
1.1 .NET 框架基本组成 .NET 框架的核心便是通用语言运行时(Commomn Language Runtime,简称 CLR),CLR 是一个可被各种不同的编程语言所使用的运行时。 托管模块(mangaed module): 一个需要 CLR 才能执行的标准 Window…...
(哈希表 ) 349. 两个数组的交集 ——【Leetcode每日一题】
❓349. 两个数组的交集 难度:简单 给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1: 输入:nums1 [1,2,2,1], nums2 [2,2] 输出:[…...
JavaScript基本语法(二)
JavaScript基本语法 1、变量1.1、简介1.2、变量命名规则1.3、JS的关键字和保留字1.4、声明提升 2、JavaScript数据类型2.1、基本类型2.2、引用类型2.3、两种类型的区别2.4、字符串常用方法 3、数据类型转换 1、变量 1.1、简介 在 JavaScript 中声明一个新变量的方法是使用关键…...
ChatGPT3.5-4资源汇总,直连无梯子
什么是ChatGPT? ChatGPT,全称:聊天生成预训练转换器(英语:Chat Generative Pre-trained Transformer),是OpenAI开发的人工智能聊天机器人程序,于2022年11月推出。该程序使用基于GPT-3.5、GPT-4…...
【Netty】使用 SSL/TLS 加密 Netty 程序(二十)
文章目录 前言一、SSL/TLS概述二、Sslhandler类 前言 回顾Netty系列文章: Netty 概述(一)Netty 架构设计(二)Netty Channel 概述(三)Netty ChannelHandler(四)ChannelP…...
runway gen2
来自Runway文生成视频ai大模型Gen-2_哔哩哔哩_bilibili来自Runway文生成视频ai大模型Gen-2,距离视频制作自由又近了一步。, 视频播放量 1651、弹幕量 0、点赞数 21、投硬币枚数 2、收藏人数 42、转发人数 22, 视频作者 旭升说, 作者简介 一起聊下互联网的那些事&…...
Day2:Windows网络编程-TCP
今天开始进入Windows网络编程的学习,在学习的时候总是陷入Windows复杂的参数,纠结于这些。从老师的讲解中,这些内容属于是定式,主要学习写的逻辑。给自己提个醒,要把精力放在正确的位置,不要无端耗费精力。…...
leetcode1985. 找出数组中的第 K 大整数
给你一个字符串数组 nums 和一个整数 k 。nums 中的每个字符串都表示一个不含前导零的整数。 返回 nums 中表示第 k 大整数的字符串。 注意:重复的数字在统计时会视为不同元素考虑。例如,如果 nums 是 ["1","2","2"]&am…...
基于深度学习的高精度野生动物检测识别系统(PyTorch+Pyside6+YOLOv5模型)
摘要:基于深度学习的高精度野生动物检测(水牛、犀牛、斑马和大象)识别系统可用于日常生活中或野外来检测与定位野生动物目标,利用深度学习算法可实现图片、视频、摄像头等方式的野生动物目标检测识别,另外支持结果可视…...
从零开始 Spring Boot 35:Lombok
从零开始 Spring Boot 35:Lombok 图源:简书 (jianshu.com) Lombok是一个java项目,旨在帮助开发者减少一些“模板代码”。其具体方式是在Java代码生成字节码(class文件)时,根据你添加的相关Lombok注解或类来…...
深入解析Spring源码系列:Day 6 - Spring MVC原理
深入解析Spring源码系列:Day 6 - Spring MVC原理 欢迎来到本系列的第六篇博客。在前几篇博客中,我们探索了Spring框架的核心概念,包括Bean的生命周期、作用域、AOP原理和事务管理。今天,我们将深入研究Spring框架中的MVC…...
Cmake中message函数 如何优雅地输出
message函数说明 在CMake中,message()函数用于向终端输出信息。 message([<mode>] "message text" ...)函数的<mode>参数可以是以下之一: (none): 等同于STATUS,但不推荐使用。STATUS: 输出的信息会被发送到CMake的…...
人工智能基础部分20-生成对抗网络(GAN)的实现应用
大家好,我是微学AI,今天给大家介绍一下人工智能基础部分20-生成对抗网络(GAN)的实现应用。生成对抗网络是一种由深度学习模型构成的神经网络系统,由一个生成器和一个判别器相互博弈来提升模型的能力。本文将从以下几个方面进行阐述࿱…...
JavaScript表单事件(上篇)
目录 一、input: 当表单元素的值发生改变时触发,适用于大多数表单元素。 二、change: 当表单元素的值发生改变且失去焦点时触发,适用于输入框、下拉列表等。 三、submit: 当表单提交时触发,适用于 form 元素。 四、reset: 当表单重置时触…...
vb6 Webview2微软Edge Chromium内核执行JS取网页数据测速
微软Edge Chromium内核执行JS获取网页数据测试 ExcuteScript eval(document.body.innerHTML) from : https://www.163.com 采集的网页HTM字符串占用字节空间1.2MB ExcuteScript回调事件中取得JS执行结果,用时 54 毫秒 其中JSON转字符13.5209毫秒 jSON数据长度: 增…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...
基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)
引言 在嵌入式系统中,用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例,介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单,执行相应操作,并提供平滑的滚动动画效果。 本文设计了一个…...
