操作系统主引导扇区代码是如何被加载到内存的?

news2024/10/5 21:13:51

1. 问题:OS引导代码为什么需要org 07c00h?

在前几天在知乎上的的一个回答《想带着学生做一个操作系统,可行性有多大?》中,我们引用了一段主引导扇区MBR中的操作系统加载代码:

	org	07c00h			; 告诉编译器程序加载到7c00处
	mov	ax, cs
	mov	ds, ax
	mov	es, ax
	call	DispStr			; 调用显示字符串例程
	jmp	$			; 无限循环
DispStr:
	mov	ax, BootMessage
	mov	bp, ax			; ES:BP = 串地址
	mov	cx, 16			; CX = 串长度
	mov	ax, 01301h		; AH = 13,  AL = 01h
	mov	bx, 000ch		; 页号为0(BH = 0) 黑底红字(BL = 0Ch,高亮)
	mov	dl, 0
	int	10h			; 10h 号中断
	ret
BootMessage:		db	"Hello, OS world!"
times 	510-($-$$)	db	0	; 填充剩下的空间,使生成的二进制代码恰好为512字节
dw 	0xaa55				; 结束标志

本来想着过了就算了,未曾想有个关注我的网友提问说:

弱弱的问一句,代码里面最开头为什么要org 07c00h?注释没看懂,是代表指示将这部分代码加载到对应内存?

本来想着在评论中解析清楚的,后来写着写着发现内容太多,且一些地方需要配合相应的一些截图才能解析清楚,所以这里干脆独立成为一篇文章来解释这个问题算了。

要解析这个问题,首先,这里我们得先了解一下操作系统启动的过程,以及相应的寄存器和内存的关系。

2. 电脑开机后是怎么一步步把操作系统引导代码加载到07c00h的

当我们按下电脑的重启按钮,加电时,我们cpu的寄存器会复位,其中大部分的寄存器都会清0,除了我们的代码段寄存器cs,将会被复位为FFFF。
在这里插入图片描述

同时,因为我们开机时,cpu是工作在实模式下的。所以我们的内存访问模型是

物理地址 = 段地址 x 16 + 偏移地址

所以开机时取得第一条指令将会来自地址:

0xFFFF x 16 + 0x0000 = 0xFFFF0

那么0xFFFF0指向的存储地址是什么内容呢?

继续之前,我们需要看下内存地址空间的分配。

我们知道8086有20根地址线,能访问的存储空间是0x00000到0xFFFFF。但是,这里需要知道的是这部分存储空间并不是全部属于我们内存条的。这里的地址空间分配是这样的:

  • 0x00000 ~ 0x9FFFF:内存
  • 0xA0000 ~ 0xEFFFF:显卡显存等外围设备
  • 0xF0000 ~ 0xFFFFF:BIOS
    在这里插入图片描述
    而我们的0xFFFF0正好是落在bios的地址空间中的。也就是说,当把0xFFFF0这个地址放到地址总线后,经过地址分配电路,将会去bios读取对应的内容来执行。当然,因为bios读取速度没有内存快,所以也有可能会将bios的代码直接映射到内存条的对应区域:
    在这里插入图片描述

那么bios中0xFFFF0的内容是什么呢?

事实上,里面是一条跳转指令。

  • EA: jmp跳转指令的机器码
  • E05B: 偏移地址
  • F000: 段地址
    在这里插入图片描述

参考我们上面的实模式下的内存访问模型,跳转的目的地址将会是0xFE05B这个地址。
在这里插入图片描述

而这个地址同样是落在bios的地址空间范畴。其实做的事情就是bios为我们提供的进行硬件自检的一系列操作。执行完这些操作后,bios最后要做的一个事情就是将我们启动盘的主引导扇区的代码给加载到内存的0x07C00开始的位置,然后执行一个跳转指令,跳转到该地址,开始执行我们的引导代码。
在这里插入图片描述

那么,这里的07c00h和我们的org 07c00h有什么关系呢?

3. org 07c00h的真实作用

假如我们想跳到代码指定一个位置进行执行,比如跳到我们代码在内存位置偏移0x0003的位置,有代码如下:

jmp 0003H

这里的跳转指令,根据我们上面的内存访问模型,实模式下,这里的目标地址将会是cs的段起始地址加上0x0003这个段内偏移地址。

假如我们现在的代码是加载到0x0000这个段,即现在的cs里面的段是0x0000,对应的段开始地址就是:

0x0000 x 16 = 0x00000

那么最终跳转jmp的物理内存目标地址就是:

0x00000 + 0x0003 = 0x00003

那最终的地址也就是我们的代码相对段起始地址偏移0x0003的位置,达到了我们预期的目标。

但是,如果我们的代码不是加载到0x00000这个段的开始位置上,而是加载到0x00000这个段偏移0x7C000即我们上面的0x07C00上呢?

那么此时的jmp 0x0003跳转的还是0x00000 + 0x0003 = 0x00003这个地址,但问题是我们现在的代码是加载到了0x7C000开始的位置,所以跳到的已经是一个我们代码范围之外的地址了,这就不是我们想要的了。
在这里插入图片描述

那么这个问题怎么解决呢?

其实就是利用org伪汇编指令就可以了。

org 7c00H
jmp 0003H

它的作用就是在汇编编译时告诉编译器:

我们的代码将会被加载到了区里段起始位置0x7c00这个位置执行,所以请将所有相关的偏移地址加上0x7c00
然后在编译后,jmp 0x0003会变成

jmp 0x7c03

即上图中的0x7c00 + 0x0003这个位置,而这,就和我们预期的目标相一致了。

4. 鸣谢

NASM Manual
https://www.bilibili.com/video/BV1xE411N74T

我是@天地会珠海分舵,能力一般,水平有限,觉得我说的还有那么点道理的不妨点个赞关注下!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PCA实现降维的过程

PCA将相关性高的变量转变为较少的独立新变量,实现用较少的综合指标分别代表存在于各个变量中的各类信息,既减少高维数据的变量维度,又尽量降低原变量数据包含信息的损失程度,是一种典型的数据降维方法。PCA保留了高维数据最重要的…

web前端期末大作业 HTML+CSS+JavaScript仿京东

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材,DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 | 在线商城购物 | 水果商城 | 商城系统建设 | 多平台移动商城 | H5微商城购物商城项目| HTML期末大学生网页设计作业,Web大学生网页 HTML&am…

SpringBoot发送邮件

06.发送邮件 在使用javaSE时&#xff0c;我们会发现发送邮件较为麻烦&#xff0c;而在SpringBoot中&#xff0c;发送邮件就变成一件较为简单的时。 导入mail的maven的启动类。 <dependency><groupId>org.springframework.boot</groupId><artifactId>…

DSPE PEG Azide, DSPE-PEG-N3;磷脂聚乙二醇叠氮

中文名称&#xff1a;磷脂聚乙二醇叠氮(DSPE-PEG-N3) 中文别名&#xff1a;N-二硬脂酰磷脂酰乙酰胺-PEG-叠氮 磷脂PEG叠氮 英文名称&#xff1a;DSPE PEG Azide, DSPE-PEG-N3 性状&#xff1a;根据不同的分子量为固体或者粘稠液体。 溶剂&#xff1a;溶于DCM&#xff0c;…

表单标签。。

一、任务目标 掌握表单标签及其属性的使用 二、任务背景 HTML表单用于收集用户输入。表单元素指的是不同类型的 input 元素、复选框、单选按钮、提交按钮等。 三、任务内容 1、<form></form>标签 用于创建HTML表单&#xff0c;常用属性如下&#xff1a; action&…

OpenGL ES 学习(一) -- 基本概念

最近在研究 SurfaceView 和 TextureView&#xff0c;发现栅格化这东西&#xff0c;一直没怎么搞明白&#xff0c;一搜都是关于 OpenGL 的&#xff0c;没办法&#xff0c;当初也是要学习这个&#xff0c;现在重试拾起。 之前接触 OpenGL &#xff0c;是主要解决一个渲染模糊问题…

JavaEE-操作系统

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录操作系统介绍操作系统的定位进程进程控制块内存管理进程间通信思维导图总结操作系统介绍 操作系统是一组做计算机资源管理的软…

文献学习01_Attention Is All You Need_20221119

论文信息 Subjects: Computation and Language (cs.CL); Machine Learning (cs.LG) &#xff08;1&#xff09;题目&#xff1a;Attention Is All You Need &#xff08;你需要的就是关注&#xff09; &#xff08;2&#xff09;文章下载地址&#xff1a;https://doi.org/10.4…

今天给大家介绍一篇基于javaWeb的汽车订票系统的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

牛客网之SQL非技术快速入门(3)-排序、关联关系

知识点&#xff1a; &#xff08;1&#xff09;order by colunm_name(s) ASC|DESC order by ID ASC,name ASC,sex DESC 不写就是默认升序&#xff0c;DESC降序 &#xff08;2&#xff09;3中关联关系&#xff1a;left join、right join、inner join/join 21、现在运营想要查…

【微信开发第四章】SpringBoot实现微信H5支付

前言 在进行微信公众号业务开发的时候,微信支付可以说是非常重要的一环。该篇文章每一步都有记录&#xff0c;力争理解的同时各位小伙伴也能够实现功能 文章目录前言1、公众号配置2、微信支付实现代码总结1、公众号配置 1、绑定域名 先登录微信公众平台进入“设置与开发”&…

阿里云架构实战之ALB(应用型负载均衡)介绍与搭建

ALB介绍 服务器端负载均衡SLB&#xff08;Server Load Balancer&#xff09;是一种对流量进行按需分发的服务&#xff0c;通过将流量分发到不同的后端服务来扩展应用系统的服务吞吐能力&#xff0c;并且可以消除系统中的单点故障&#xff0c;提升应用系统的可用性。 阿里云负…

代码随想录算法训练营第60天 | 一刷结束篇 84.柱状图中最大的矩形

代码随想录系列文章目录 一刷总结篇 文章目录代码随想录系列文章目录84.柱状图中最大的矩形dp 普通思路单调栈一刷总结篇84.柱状图中最大的矩形 题目链接 这道题和接雨水是两个相似的题&#xff0c;相辅相成的那种&#xff0c;双指针是过不了力扣的会超时&#xff0c;所以我也…

pandas提取键值对(json和非json格式)

&#xff08;欢迎大家关注我的公众号“机器学习面试基地”&#xff0c;之后将在公众号上持续记录本人从非科班转到算法路上的学习心得、笔经面经、心得体会。未来的重点也会主要放在机器学习面试上&#xff01;&#xff09; 最近工作中需要解析一些有模型输入输出信息的csv日志…

SpringBoot+Mybaits搭建通用管理系统实例七:访问接口Api层功能实现

一、本章内容 系统api接口层实现,实现系统对外接口相应功能定义及实现,并通过Swagger实现接口文档的自动生成。 完整课程地址 二、开发视频 SpringBoot+Mybaits搭建通用管理系统实例二:api层实现 三、代码实现 使用基类的方式实现各方法接口的抽象实现,使用泛型的方式指定具…

linux上配置jdk和maven环境 (deepin适用)

前言 安装那些&#xff0c;就不说了&#xff0c;应该大家都下好才来配置的&#xff0c;下载安装的话&#xff0c;直接解压到一个目录就好&#xff0c;给个链接给你 jdk8下载链接&#xff1a; https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html 命…

Docker Buildkit(新增 --mount、--security、--network 等特性)

BuildKit是Docker官方社区推出的下一代镜像构建神器。 可以更加快速&#xff0c;有效&#xff0c;安全地构建docker 镜像&#xff0c;自 docker v18.06 版本起已经集成了该组件。 Buildkit 是下一代 docker 构建组件&#xff0c;拥有众多特性&#xff1a; 自动垃圾收集可扩展…

静态WEB容器镜像最小化实践

在现代的B/S架构应用中&#xff0c;我们会做前后端分离&#xff0c;某些前端Web服务会将编译完成的静态文件放到一个web服务器进行部署。例如&#xff0c;我的博客也是基于Hugo编译的静态文件来进行部署的。 那在容器化部署模式下&#xff0c;我们需要基于一个web服务的基础容…

js:什么是编译时和运行时

编译时 源代码编译为机器可执行的二进制码。 编译过程中一般会识别你代码中的语法错误等问题&#xff0c;这个错误就叫编译时错误&#xff0c;做的一些检查也叫做编译时类型检查或者静态类型检查&#xff0c;因为静态就意味着代码还没有放到内存里去运行&#xff0c;只是把代…

九.STM32F030C8T6 MCU开发之电源掉电数据保存案例

九.STM32F030C8T6 MCU开发之电源掉电数据保存案例 0.总体功能概述 使用STD库–en.stm32f0_stdperiph_lib_v1.6.0。 1.掉电数据保存背景 掉电保存数据的时间内 电源稳定。也就是数据保存时间要尽量短,电源稳定要尽量长。 第一种,采用备用电池的方法来实现,增加了电池和更…