为什么是0x7c00

计算机执行到这份上,bios也即将完成自己的历史使命了,完成之后,它又将睡去。想到这里,心中不免一丝忧伤,甚至有些许挽留它的想法。可是,这就是它的命,它生来被设计成这样,在它短暂的一生中已经为后人创造了足够的精彩。何况,在下一次开机时,bios还会重复这段轮回,它并没有消失。好了,让伤感停止,让梦想前行。

先说重点,bios最后一项工作校验启动盘中,位于0盘0道1扇区的内容。在此插播一段小告示:在计算机中是习惯以0做为起始索引的,因为人们已经习惯了偏移量的概念,无论是机器眼里和程序员眼里,用“相对”的概念,即偏移量来表示位置显得很直观,所以很多指令中的操作数都是用偏移量表示的。0盘0道1扇区本质上就相当于0盘0道0扇区。为什么称为1呢,因为硬盘扇区的表示法有两种,我们描述0盘0道1扇区用的便是其中的一种:CHS方法,即柱面Cylinder 磁头Header 扇区Sector(另外一种是LBA方式,暂不关心),“0盘”说的是0磁头,因为一张盘是有上下两个盘面的,一个盘面上对应一个磁头,所以用磁头Header来表示盘面。“0道”是指0柱面,柱面Cylinder指的是所有盘面上、编号相同的磁道的集合,形象一点描述就是把很多环叠摞在一起的样子,组合在一起之后是一个立体的管状。“1扇区”才是我们要解释的部分,将磁道等距划分成一段段的小区间,由于磁道是圆形,确切地说是圆环,所以这些被划分出来的小区间便是扇形,所以称为扇区。好了,背景交待完了,重点来了,在CHS方式中扇区的编号是从1开始的,不是0,不是0,原谅我说了两次,良苦用心你懂的,所以0盘0道1扇区是其实就相当于0盘0道0扇区,它就是磁盘上最开始的那个扇区。而LBA方式中,扇区编号是从0开始的。关于硬盘的知识我会在以后章节专门来讲,这里我若没表达清楚,大家先不要着急,只要知道MBR所在的位置是磁盘上最开始的那个扇区就行了。继续说,如果此扇区末尾的两个字节分别是魔数0x55和0xaa,bios便认为此扇区中确实存在可执行的程序(在此先剧透一下,此程序便是久闻大名的主引导记录MBR),便加载到物理地址0x7c00,随后跳转到此地址,继续执行。

这里有个小细节,bios跳转到0x7c00是用jmp 0:0x7c00实现的,这是jmp指令的直接绝对远转移用法,段寄存器cs会被替换,这里的段基址是0,即cs由之前的0xf000变成了0。如果此扇区的最后2个不是0x55和0xaa,即使里面有可执行代码也无济于事了,bios不认,它也许还认为此扇区是没格干净呢,嘿嘿。

不过,这就又抛出两个问题:

  1. 1.为什么是0盘0道1扇区的内容。
  2. 2.为什么是物理地址0x7c00而不是个好记或好看的其它地址。

先回答第1个,我想这个问题不用官方解释了,因为官方确实没什么好说的,不过他们出于尊重客户,还是会像我一样说出类似下面的话。

我就个人观点给大家一个理由,未经核实,仅是自己一面之词,请大家提高警惕,小心谨慎^—^。

在计算机中处处充满了协议、约定,所以,将0盘0道1扇区做为mbr的栖身之地,我完全可以理解为规定。我们反证一下,如果不存在这个“规定”,会发生什么。当然,此扇区最初是给bios使用的,咱们设想一下bios的工作将变成怎样。

主引导记mbr是段程序,无论是位于软盘、硬盘、或者其它介质,总该有个地方保存它。Ok,现在不告诉bios 它存储在哪个位置了。bios只好将所有检测到的存储设备上的每一个存储单位都翻一遍,挨个对比,如果发现该存储单位最后的两个字节是0x55和0xaa,就认为它mbr。这就好比查字典一样,不用偏旁部首和拼音检索的方法,只能一页一页翻了。

几经花开花落,找到mbr的那一刻,bios满脸疲惫地说:“你是我找了好久好久的那个人”。mbr抬起经不起岁月等待的脸:“难得你还认得我,我等你等到花儿都谢了”。其实bios的心声是:“看我手忙脚乱的样子,你们这是要闹哪样啊。就那么512字节的内容,害我找遍全世界,我们是在跑接力赛啊,下一棒的选手我都不知道在哪里……以后让它站在固定的位置等我!”。

由于0盘0道1扇区是磁盘的第一个扇区,mbr选择了离bios最近的位置站好了,从此以后再也不担心被bios骂了。

计算机中处处有固定写死的东西,还用举个例子吗?不用了吧?因为任何一个魔数都是啊^_^,有请下一个魔数0x7c00登场。

至于0x7c00,很久之前,比我好奇心大的人查遍了intel开发手册都没找到相关的说明。要想知道事情的来龙去脉,还是要从个人电脑的老祖宗说起,同样是很久很久以前……1981年8月,IBM公司生产了世界上第一台个人电脑PC 5150,所以它就是现代x86个人电脑兼容机的祖先。说到有关历史的东西,不给来点真相就感觉气场不足,上图啦,这是IBM PC 5150,有没有感受到计算机文化底蕴呢。

既然intel开发手册中没有相关说明,那咱们就朝其它方向找答案,换句话说,既然不是cpu的硬性规定,那很可能就是代码中写死的。为了搞清楚0x7c00是哪里来的,咱们先探索下 "IBM PC 5150"的bios的秘密。请先深深呼吸一大口气,“0x7C00”最早出现在IBM 公司出产的个人电脑PC5150的ROM BIOS的 INT19H中断处理程序中,说了这么多定语,感觉气都喘不上来了。

通电开机之后,bios处理程序开始自检,随后,调用bios中断0x19h,即 call int 19h。在此中断处理函数中,bios要检测这台电脑有多少硬盘或软盘,如果检测到了任何可用的磁盘,bios就把它的第一个扇区加载到0x7c00.

现在应该搞清楚了为什么在x86手册里找不到它的说明了,它是属于bios中的规范。似乎这下好办了,既然是bios中的规范,那肯定是IBM PC 5150 BIOS 开发团队规定的这个数。

个人计算机肯定要运行操作系统,在这台计算机上,运行的操作系统是DOS 1.0,不清楚此系统要求的最小内存是16KB还是32KB,反正PC 5150 BIOS研发工程师就假定其是32K,所以此版本bios是按最小内存32KB研发的。

MBR不是随便放在哪里都行的,首先不能覆盖已有的数据,其次,不能过早的被其它数据覆盖。不覆盖已有数据,这个好理解。说一下后面这个“其次”。通常,MBR的任务是加载某个程序(这个程序一般是内核加载器,很少有直接加载内核的)到指定位置,并将控制权交给它。所谓的交控制权就是jmp过去而已。之后MBR就没用了,被覆盖也没关系。我说的过早被覆盖,是指不能让mbr破坏自己,比如被加载的程序,如内核加载器,其放置的内存位置若是MBR自己所在的范围,这不就是破坏自己了吗,这就是我所说的“过早”了,怎么也得等mbr执行完才行。

重现一下当时的内存使用情况:8086cpu要求物理地址0x0~0x3FF存放中断向量表,所以此处不能动了,再选新的地方看看。按DOS 1.0要求的最小内存32KB来说,MBR希望给人家尽可能多的预留空间,这样也是保全自己的作法,免得过早被覆盖。所以MBR只能放在32KB的末尾。MBR本身也是程序,是程序就要用到栈,栈也是在内存中的,所以MBR虽然本身只有512字节,但还要为其所用的栈分配点空间,所以其实际所用的内存空间要大于512字节,估计1k内存够用了。结合以上三点,选择32KB中的最后1K最为合适,那此地址是多少呢。32KB换算为16进制为0x8000,减去1K(0x400)的话,等于0x7c00。这就是倍受质疑的0x7c00的由来,这下清楚了。可见,加载MBR的位置是取决于操作系统本身所占内存大小和内存布局。

我想大家现在都心痒痒了吧,说了这么久,cpu中运行的都是bios的代码,连自己一句代码都没跑起来呢。事不宜迟,马上写一个MBR,先让它跑起来再说。

一步步编写操作系统 08 bios跳转到神奇的内存地址0x7c00相关推荐

  1. 一步步编写操作系统 71 直接操作显卡,编写自己的打印函数71-74

    一直以来,我们在往屏幕上输出文本时,要么利用bios中断,要么利用系统调用,这些都是依赖别人的方法.咱们还用过一个稍微有点独立的方法,就是直接写显存,但这貌似又没什么含量.如今我们要写一个打印函数了, ...

  2. 一步步编写操作系统 69 汇编语言和c语言共同协作 70

    由于有了上一节的铺垫,本节的内容相对较少,这里给大家准备了两个小文件来实例演示汇编语言和c语言相互调用. 会两种不同语言的人,只是掌握了同一件事物的两种表达方式.人在学习一种新语言时,潜意识里是建立了 ...

  3. 一步步编写操作系统 62 函数调用约定

    由于我们要将c语言和汇编语言结合编程啦,所以一定会存在汇编代码和c代码相互调用的问题,有些事情还是要提前交待给大家的,本节就是要给大家说下函数调用规约中的那些事儿. 函数调用约定是什么? 调用约定,c ...

  4. 一步步编写操作系统21 x86虚拟机bochs 跟踪bios

    为了让大家更好的理解bios是怎样被执行的,也就是计算机中第一个软件是怎样开始的,咱们还是先看下图3-17.在图的上面第5行,显示的是下一条待执行的指令,这是程序计数器(PC)中的值,在x86上的程序 ...

  5. 一步步编写操作系统 33 利用bios中断0x15子功能0xe820获取内存

    咱们先介绍0xE820子功能,这是最灵活的内存获取方式. bios中断 0x15的子功能0xE820能够获取系统的内存布局,由于系统内存各部分的类型属性不同,bios就按照类型属性来划分这片系统内存, ...

  6. 一步步编写操作系统 07 开机启动bios

    bios是如何苏醒的 bios其实一直睡在某个地方,直到被唤醒--前面热火朝天的说了bios的功能和内存布局,似乎还没说到正题上,bios是如何启动的呢.因为bios是计算机上第一个运行的软件,所以它 ...

  7. 一步步编写操作系统 30 cpu的分支预测简介

    人在道路的分岔口时要预测哪条路能够到达目的地,面对众多选择时,计算机也一样要抉择,毕竟计算机的运行方式是以人的思路来设计的,计算机中的抉择其实就是人在抉择. cpu中的指令是在流水线上执行.分支预测, ...

  8. 一步步编写操作系统 23 重写主引导记录mbr

    本节我们在之前MBR的基础上,做个稍微大一点的改进,经过这个改进后,我们的MBR可以读取硬盘.听上去这可是个大"手术"呢,我们要将之前学过的知识都用上啦.其实没那么大啦,就是加了个 ...

  9. 一步步编写操作系统 19 改进MBR,直接操作显卡

    到目前为止,说了一部分有关显存的内容,这对于一般的输出来说已经足够了,下面咱们可以尝试写显存啦.我们将之前MBR改造一下,保留滚屏的操作,只修改有关输出的部分.即把通过bios的输出改为通过显存,你会 ...

最新文章

  1. 字节流与字符流基本操作
  2. MoCo论文中的Algorithm 1伪代码解读
  3. 1.4 isAlive()方法
  4. PAT1054 求平均值 (20 分)【从非法输入字符串中获取合法输入 cin.putback()】
  5. 深度学习(二十九)——Normalization进阶, CTC
  6. Postman: Test
  7. excel表格怎么调整行高和列宽_excel表格怎么调整高度和宽度
  8. php调用winhttp,HTTP HTTPS POST GET(包含curl版本和winhttp两种实现)
  9. 深度教练:让深度学习模拟人类教学过程,大幅减少训练数据和时间
  10. (转)cocos2d-x学习笔记(五)仿真树叶飘落效果的实现(精灵旋转、翻转、钟摆运动等综合运用)
  11. DNS用的是TCP协议还是UDP协议
  12. 2021年我与我家公主的五一小长假---游记
  13. 2021高考秦安一中成绩查询,2021年天水高考状元是谁分数多少分,历年天水高考状元名单...
  14. mysql 设置 sql_mode
  15. 深度学习方法(二十一):常用权重初始化方法Xavier,He initialization的推导
  16. OpenStack-Pike版Ironic安装指导分析-(上)
  17. java enum枚举型使用
  18. 20220221量化打板模型预测
  19. python做一个网页、让用户上传数据_一个简单的网站爬虫教程,让你了解爬虫的步骤,爬虫网页数据采集...
  20. 静电放电防护设计规范和指南

热门文章

  1. 日志log4cxx 封装、实例讲解、配置文件log4cxx.properties
  2. 【Breadth-first Search 】785. Is Graph Bipartite?
  3. 复盘二进制的习题(2)
  4. [剑指offer][JAVA]面试题[第23题][合并K个排序链表][分治][优先队列]
  5. unionall mysql_5分钟了解MySQL5.7union all用法的黑科技
  6. python u_对python 命令的-u参数详解
  7. html5列表菜单特效,HTML5 SVG汉堡包菜单按钮分段动画特效
  8. matlab 控制实验指导,智能控制系统-实验指导书-实验一-BP算法的MATLAB实现
  9. python爬取小说出现乱码_详解Python解决抓取内容乱码问题(decode和encode解码)
  10. qt中的qwidget如何实现自定义部件_2.3信号和槽(中)