linux0.11源码分析第二弹——setup.s内容

🚀 前言

    继上篇博客分享了boot文件的内容后,本篇博客进而来到第二个文件: setup.s ,对应了《linux源码趣读》的第5~8回。这部分的功能主要就是做了 三件事 ,第一件事是做代码搬运和临时变量存放,第二件事是突破寻址瓶颈,第三件事是进入保护模式,具体如何操作以及为什么要做这些,本篇博客回一一解答,希望各位给个三连,拜托啦,这对我真的很重要!!!

目录

  • 🚀 前言
  • 🏆代码搬运和临时变量存放
    • 📃前期准备
    • 📃system代码存放
  • 🏆段描述符
  • 🏆突破寻址瓶颈
  • 🏆进入保护模式
  • 其他部分
  • 🎯总结
  • 📖参考资料

🏆代码搬运和临时变量存放

📃前期准备

    首先做了一些准备工作,比如调用0x10中断的03功能, 读取光标位置 ,在linux中源码如下:

start:

; ok, the read went well so we get current cursor position and save it for
; posterity.

	mov	ax, #0x9000	; this is done in bootsect already, but...
	mov	ds,ax
	mov	ah,#0x03	; read cursor pos
	xor	bh,bh
	int	0x10		; save it in known place, con_init fetches
	mov	[0],dx		; it from 0x90000.

    调用的方法就是设置ah为0x03,同时用int指令。结果会保存在dx寄存器中,高8位存储行号,低8位存储列号。然后mov [0], dx,再结合ds段寄存器是0x9000,结果就是就是把光标位置存储在0x9000这个内存地址。

    再之后就是 获取一些信息 。罗列出的代码如下所示,分别为内存信息,显卡显示模式,检查显示方式,获取第一块和第二块磁盘信息。

; Get memory size (extended mem, kB)

	mov	ah,#0x88
	int	0x15
	mov	[2],ax

; Get video-card data:

	mov	ah,#0x0f
	int	0x10
	mov	[4],bx		; bh = display page
	mov	[6],ax		; al = video mode, ah = window width

; check for EGA/VGA and some config parameters

	mov	ah,#0x12
	mov	bl,#0x10
	int	0x10
	mov	[8],ax
	mov	[10],bx
	mov	[12],cx

; Get hd0 data

	mov	ax,#0x0000
	mov	ds,ax
	lds	si,[4*0x41]
	mov	ax,#INITSEG
	mov	es,ax
	mov	di,#0x0080
	mov	cx,#0x10
	rep
	movsb

; Get hd1 data

	mov	ax,#0x0000
	mov	ds,ax
	lds	si,[4*0x46]
	mov	ax,#INITSEG
	mov	es,ax
	mov	di,#0x0090
	mov	cx,#0x10
	rep
	movsb

    经过上面的操作,最后的内存存放内容如下所示。

在这里插入图片描述

    接下来 关闭中断 ,因为后面要把原本是BIOS写好的中断向量表覆盖掉,即原来内存中0 ~ 0x3FF的位置,要存放系统编译后的文件,因此此时是不能允许中断进来的,禁止终端采用如下指令:

cli

📃system代码存放

    接下来就是要把系统代码的240个扇区从上一个boot文件设置的0x10000~0x90000处统统移动到 0 ~ 0x80000 处。

mov	ax,#0x0000
	cld			; 'direction'=0, movs moves forward
do_move:
	mov	es,ax		; destination segment
	add	ax,#0x1000
	cmp	ax,#0x9000
	jz	end_move
	mov	ds,ax		; source segment
	sub	di,di
	sub	si,si
	mov 	cx,#0x8000
	rep
	movsw
	jmp	do_move

    对这段代码而言,将sidi设置为了0,然后调用rep movsw进行复制,复制次数是0x80000次。现在来说,内存的分布情况如下图所示:

在这里插入图片描述

🏆段描述符

    首先需要知道为什么需要 段描述符 。其实这个是一个x86架构的历史遗留问题,现在的CPU 几乎都支持32位或64位模式了,但仍然需要解决一下16位实模式下的CPU这个历史遗留问题,于是就出现了模式转换,从实模式切换到保护模式。

    所谓的实模式,即CPU可以访问任何物理地址,只能访问20根地址线所能达到的1M的大小。保护模式则可以突破这个限制,并引入了分页管理的概念,对内存地址进行了保护。关于具体区别,其中也有很深的渊源,日后可以单独出篇博客,这里还是回归主线,只是简单讲一下实模式与保护模式的寻址区别。

    实模式的寻址比较简单粗暴,采用: 段基址+偏移地址 的方式。保护模式的寻址模式则相对复杂很多:首先根据段寄存器(ds,es,ss,cs)存储的值作为 段选择子 ,段选择子去全局描述符表(GDT)中找 段描述符 ,在段描述符中取出基地址,最后加上偏移地址构成最终的物理地址。

    这个GDT存发在内存的哪个地方呢?答案是gdtr寄存器。这个寄存器是一个48位的寄存器,结构如下所示:

在这里插入图片描述
    具体内存中是怎么实现的呢,如下所示:

lgdt	gdt_48		; load gdt with whatever appropriate

gdt_48:
	.word	0x800		; gdt limit=2048, 256 GDT entries
	.word	512+gdt,0x9	; gdt base = 0X9xxxx

    这段代码一点一点来分析,使用lgdt指令可将后面的 gdt_48放入到GDTR寄存器中,后面是解释gdt_48标签的内容。第一行表示的是GDT界限,即多少个段描述符,0x800换算十进制是2048,一个段描述符是64位,8个字节(待会细说),因此一共能存 256个GDT 。第二行是GDT的内存起始地址,段基址是0x90000,512是0x200,因此最后存放的位置就是0x90200+gdt

    gdt标签又在哪里呢,代码先放一放,先来介绍一下段描述符,其结构如下所示:

在这里插入图片描述
    还记得上文提到的保护模式吗,保护模式是会做区分的,因此此时csds这些不同的段终于可以有各自的意义了。段描述符可以给代码段,数据段,其区分的方式是看其中的S位,1是代码段或数据段。

    好了,接下来我们可以回到源码,看刚刚我们要看的gdt标签处的代码了,如下所示:

gdt:
	.word	0,0,0,0		; dummy

	.word	0x07FF		; 8Mb - limit=2047 (2048*4096=8Mb)
	.word	0x0000		; base address=0
	.word	0x9A00		; code read/exec
	.word	0x00C0		; granularity=4096, 386

	.word	0x07FF		; 8Mb - limit=2047 (2048*4096=8Mb)
	.word	0x0000		; base address=0
	.word	0x9200		; data read/write
	.word	0x00C0		; granularity=4096, 386

    来分析这段代码,首先给了四个0,因此 最开始是一个空的描述符 ,然后看第二大段,第二大段最开始给了0x07ff,对应上图的段限长,0x7ff2047,每个段至少占用一个字节,因此是2048字节,即2MB,然后0x0000是段基地址,随后的0x9A00涉及的位比较多,参考上面的表涉及到了S位,TYPE位,Base位,展开二进制后可以发现S位是1,因此 该段表示代码段 ,后面的0x00c0则对应上图剩下的位。对于第二段同理,可以看到可以代表是数据段。

    上面看不懂没关系,只需要关注下面的逻辑关系即可,下面这张图也是段选择子中描述符索引的内容,比如段选择子为1,表示代码段:
在这里插入图片描述


    再来回顾一下寻址方式,这个很重要,先去段寄存器拿段选择子,然后根据段选择子到GDT中拿段基地址,最后加上偏移得到物理地址,流程如下所示:

在这里插入图片描述

    截止目前为止,内存中的结构如下所示:

在这里插入图片描述

🏆突破寻址瓶颈

    上文有提到,实模式下是20位寻址线,即只可访问1MB的空间,这里突破寻址瓶颈顾名思义就是突破1MB的寻址空间。至于为什么到了如今32位,甚至64位的今天,还需要保留这个20位寻址呢,那只能说是历史遗留问题,为了兼容。如果不突破这个20位寻址限制,那即使有32位寻址线,仍然会收到20位寻址线的限制。

    换到具体代码中的操作如下所示:

mov	al,#0xD1		; command write
out	#0x64,al
mov	al,#0xDF		; A20 on
out	#0x60,al

    开启A20门有几种方式,第一种是键盘控制,第二种是I/O端口0x92来处理,第三种是使用int 15来处理。这里之前关闭了中断,代码里是用的键盘控制。具体是向端口 0x64 发送 0xD1,其通常用于重置键盘控制器的状态,使其能够正确地处理后续的命令。然后,向端口 0x60 发送 0xDF来开启A20。

🏆进入保护模式

    想要开启保护模式很简单,只需要将cr0寄存器的位0置1即可,在汇编中可以采用指令lmsw写入,实际代码如下所示:

mov	ax,#0x0001	; protected mode (PE) bit
lmsw	ax		; This is it;
jmpi	0,8		; jmp offset 0 of segment 8 (cs)

    在代码的最后,使用jmpi指令跳转到一个新的位置。那么这个位置是什么呢?这里有个注意点,此时已经是变为保护模式了,寻址方式和实模式是不一样的。该指令将cs置为8,ip指针置为0,8展开二进制并对应下面段选择子结构可以发现,段描述符索引为1,对照上文中全局描述符表可以发现,是代码段描述符,段基址为0,偏移也是0,所以最终跳转的位置还是0地址,即整个system这个大模块。
在这里插入图片描述

其他部分

    在这里重新编程了中断,可以不用看,代码如下:

mov	al,#0x11		; initialization sequence
out	#0x20,al		; send it to 8259A-1
.word	0x00eb,0x00eb		; jmp $+2, jmp $+2
out	#0xA0,al		; and to 8259A-2
.word	0x00eb,0x00eb
mov	al,#0x20		; start of hardware int's (0x20)
out	#0x21,al
.word	0x00eb,0x00eb
mov	al,#0x28		; start of hardware int's 2 (0x28)
out	#0xA1,al
.word	0x00eb,0x00eb
mov	al,#0x04		; 8259-1 is master
out	#0x21,al
.word	0x00eb,0x00eb
mov	al,#0x02		; 8259-2 is slave
out	#0xA1,al
.word	0x00eb,0x00eb
mov	al,#0x01		; 8086 mode for both
out	#0x21,al
.word	0x00eb,0x00eb
out	#0xA1,al
.word	0x00eb,0x00eb
mov	al,#0xFF		; mask off all interrupts for now
out	#0x21,al
.word	0x00eb,0x00eb
out	#0xA1,al

    经过以上代码,现在中断号与用途的对应关系如下所示:

在这里插入图片描述

🎯总结

    整个setup部分就做了三件事,第一件事是做代码搬运和临时变量存放,第二件事是突破寻址瓶颈,第三件事是进入保护模式。在代码搬运阶段,整个操作系统的代码被放到了内存中0 ~ 0x8000的位置。突破寻址瓶颈可以将寻址空间突破1MB。进入保护模式要注意描述符表以及保护模式下的寻址方式的改变。

📖参考资料

[1] linux源码趣读
[2] 一个64位操作系统的设计与实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/938777.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Halcon中histo_2dim(Operator)算子原理及应用详解

在Halcon中,histo_2dim算子是一个用于计算双通道灰度值图像的直方图的工具。以下是对该算子的原理及应用的详细解释: 一、原理 histo_2dim算子的函数原型为:histo_2dim(Regions, ImageCol, ImageRow : Histo2Dim : : )。 输入参数&#xff…

(vue)el-table在表头添加筛选功能

(vue)el-table在表头添加筛选功能 筛选前&#xff1a; 选择条件&#xff1a; 筛选后&#xff1a; 返回数据格式: 代码: <el-tableref"filterTable":data"projectData.list"height"540":header-cell-style"{border-bottom: 1px soli…

使用 Marp 将 Markdown 导出为 PPT 后不可编辑的原因说明及解决方案

Marp 是一个流行的 Markdown 演示文稿工具&#xff0c;能够将 Markdown 文件转换为 PPTX 格式。然而&#xff0c;用户在使用 Marp 导出 PPT 时&#xff0c;可能会遇到以下问题&#xff1a; 导出 PPT 不可直接编辑的原因 根据 Marp GitHub 讨论&#xff0c;Marp 导出的 PPTX 文…

UE5安装Fab插件

今天才知道原来Fab也有类似Quixel Bridge的插件&#xff0c;于是立马就安装上了&#xff0c;这里分享一下安装方法 在Epic客户端 - 库 - Fab Library 搜索 Fab 即可安装Fab插件 然后重启引擎&#xff0c;在插件面板勾选即可 然后在窗口这就有了 引擎左下角也会多出一个Fab图标…

Gin- Cookie\Session相关

Cookie&#xff0c;Session是什么&#xff1f; Cookie直译小饼干&#xff0c;是一些数据信息&#xff0c;类似于小型文本文件&#xff0c;存储在浏览器上。Cookie是进行第一次登录之后&#xff0c;由服务器创建后返回给浏览器的。之后&#xff0c;每当浏览器再次向同一服务器发…

使用Python打造高效的PDF文件管理应用(合并以及分割)

在日常工作和学习中&#xff0c;我们经常需要处理大量PDF文件。手动合并、分割PDF不仅耗时&#xff0c;还容易出错。今天&#xff0c;我们将使用Python的wxPython和PyMuPDF库&#xff0c;开发一个强大且易用的PDF文件管理工具。 C:\pythoncode\new\mergeAndsplitPdf.py 所有代…

深度学习中自适应学习率调度器

传统观点认为&#xff0c;太大的学习率不利于优化深度神经网络&#xff0c;而相比固定的学习率而言&#xff0c;变化的学习率更能提供快速的收敛。基于此&#xff0c;本文作者基于理论基础提出了一个计算深度神经网络学习率的新方法。实验结果证明了该方法的有效性。 训练神经…

文献研读|基于像素语义层面图像重建的AI生成图像检测

前言&#xff1a;本篇文章主要对基于重建的AI生成图像检测的四篇相关工作进行介绍&#xff0c;分别为基于像素层面重建的检测方法 DIRE 和 Aeroblade&#xff0c;以及基于语义层面重建的检测方法 SimGIR 和 Zerofake&#xff1b;并对相应方法进行比较。 相关文章&#xff1a;论…

ElasticSearch06-分片节点分配

零、文章目录 ElasticSearch06-分片节点分配 1、单节点多分片多副本 &#xff08;1&#xff09;启动一个空节点 节点的配置如下 cluster.name: mycluster node.name: node-01 node.master: true node.data: true network.host: 127.0.0.1 http.port: 9201 transport.tcp.p…

信息学奥赛一本通 1438:灯泡 | 洛谷 P5931 [清华集训2015] 灯泡

【题目链接】 ybt 1438&#xff1a;灯泡 洛谷 P5931 [清华集训2015] 灯泡 【题目考点】 1. 三分 求函数极值 2. 相似三角形 3. 对钩函数 【解题思路】 首先考虑影子还没有到达对面墙壁的情况 记BM长度为x&#xff0c;影子为AM&#xff0c;长度为L。三角形ABC相似于三角…

揭开 Choerodon UI 拖拽功能的神秘面纱

01 引言 系统的交互方式主要由点击、选择等组成。为了提升 HZERO 系统的用户体验、减少部分操作步骤&#xff0c;组件库集成了卓越的拖拽功能&#xff0c;让用户可以更高效流畅的操作系统。 例如&#xff1a;表格支持多行拖拽排序、跨表数据调整、个性化调整列顺序&#xff1…

【物联网技术与应用】实验4:继电器实验

实验4 继电器实验 【实验介绍】 继电器是一种用于响应施加的输入信号而在两个或多个点或设备之间提供连接的设备。换句话说&#xff0c;继电器提供了控制器和设备之间的隔离&#xff0c;因为设备可以在AC和DC上工作。但是&#xff0c;他们从微控制器接收信号&#xff0c;因此…

fpga系列 HDL:Quartus II 时序约束 静态时序分析 (STA) test.out.sdc的文件结构

test.out.sdc的文件结构 ## Generated SDC file "test.out.sdc"## Copyright (C) 1991-2013 Altera Corporation ## Your use of Altera Corporations design tools, logic functions ## and other software and tools, and its AMPP partner logic ## functions,…

Windows安全中心(病毒和威胁防护)的注册

文章目录 Windows安全中心&#xff08;病毒和威胁防护&#xff09;的注册1. 简介2. WSC注册初探3. WSC注册原理分析4. 关于AMPPL5. 参考 Windows安全中心&#xff08;病毒和威胁防护&#xff09;的注册 本文我们来分析一下Windows安全中心&#xff08;Windows Security Center…

HTML中的Vue3解析!

#Vue 3 是一个用于构建用户界面的渐进式 JavaScript 框架。它在 HTML 中发挥着重要的作用&#xff0c;可以让开发者轻松地创建交互式的网页应用。与 HTML 结合时&#xff0c;Vue 3 通过自定义指令、组件等方式增强了 HTML 的功能。# 一、vue的概述 Vue 采用了双向数据绑定机制…

ARM嵌入式学习--第八天(PWM)

PWM -PWM介绍 PWM&#xff08;pulse Width Modulation&#xff09;简称脉宽调制&#xff0c;是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术&#xff0c;广泛应用在测量&#xff0c;通信&#xff0c;工控等方面 PWM的频率 是指在1秒钟内&#xff0c;信号从…

TongESB7.1.0.0安装参考指引+测试参考(by lqw)

文章目录 安装安装准备配置jdk安装管理中心&#xff08;manager&#xff09;安装运行时(server)安装mysql并配置manager&#xff08;新装阶段考虑&#xff09;放入授权启动内置redis启动内置redis启动manager和server停止manager和server访问控制台如何在控制台上重置密码 测试…

【现代C++开发】使用现代的C++快速开发一款串口读写软件

文章目录 前言一、必要条件二、实现步骤1.创建项目2.配置代码提示3.安装依赖3.编译程序4. 编写实现代码 前言 最近关于C闹出来的动静态势挺大的&#xff0c;主要是由于爱美丽卡开始抵制C&#xff0c;最近有不少文章都报道了这件事&#xff0c;比如 即使C到了这个时候&#xf…

linux上qt打包(二)

sudo apt install git 新建一个文件夹 名为xiazai&#xff0c; chmod -R 777 xiazai cd xiazai 并进入这个文件夹&#xff0c;然后clone git clone https://github.com/probonopd/linuxdeployqt.git 此处可能要fanQiang才能下 cd linuxdeployqt文件夹 下载平台需要的…

电脑开机提示error loading operating system怎么修复?

前一天电脑还能正常运行&#xff0c;但今天启动时却显示“Error loading operating system”&#xff08;加载操作系统错误&#xff09;。我已经仔细检查了硬盘、接线、内存、CPU和电源&#xff0c;确认这些硬件都没有问题。硬盘在其他电脑上可以正常使用&#xff0c;说明不是硬…