结合上面的文章,CPU上电后第一条指令是通过CS:IP来指定的,CPU厂家会给其初始值,对于386处理器来说,CPU第一条指令地址是

                  0xFFFFFFF0

  这里会有一个问题,CPU怎么能一上来就去0xFFFFFFF0取指令呢?因为此时的内存都没有初始化呢,内存中什么都没有,第一条指令毫无疑问肯定在BIOS中,现在用来烧写BIOS的Flash芯片一般也就256KB、1MB、4MB,都是非常小的,怎么也没有0xFFFFFFF0这个地址的。

  这里就需要说一下x86的地址编码方式了,我们平时说的内存,主存是指RAM,但是这里会有些问题,因为RAM是从0开始的一个地址范围,而ROM也是从0开始的一个地址范围,当我们要访问一个地址,比如0x100,此时到底是去RAM里找还是去ROM里找呢?

  x86解决这个问题的方法是“统一编码”,也可以叫做地址映射,也就是在CPU眼里,它只看到一块打的空间,对于32位CPU,从0开始,4G结束,64位的CPU最大范围就更大了,CPU才不懂什么叫RAM,什么叫ROM,什么叫硬盘的,地址映射的概念就是给地址分段,不同位置是有不同的作用的,大部分是用来给程序运行的RAM的,但还有部分是映射给ROM,IO或者其他设备,下图是一种典型的地址映射关系:

  

  那么问题又来了,上面不是说CPU上电后会去0xFFFFFFF0处取第一条指令,这条指令肯定是在BIOS中,但是上图中BIOS的映射地址时0xF0000,这个就有点懵了,到底是为什么呢?那么BIOS代码到底映射在什么位置呢?

  答案是--两个地址都有,BIOS的代码肯定是存在EPROM中的,CPU中的硬件回把EPROM芯片映射到2个地方,一个是从0xFFFFFFFF(4G)处向下扩展,一个是从0xFFFFF(1MB)处向下扩展,第一个映射是因为第一条指令在0xFFFFFFF0处,所以EPROM必须在哪个位置,第二个映射是为了兼容,在16位时代就有了,另外地址映射是占据地址空间,总是你的PC机只有2G内存也没关系,因为病没有使用内存,使用的只是地址空间,所到底对于CPU来说,它才不知道哪是哪,它只知道服从硬件安排,上面的所有所有地址映射,都是给程序员看的,不是给CPU看的,CPU只认各种“门”电路。

  那么第一条指令的内容是什么呢?

  这是比较容易产生混淆的地方,多数人说第一条指令是个长跳转(long jmp),跳转到0~0xFFFFF(0-1MB)这一段,然后再执行BIOS剩余的指令,但是intel手册中却又这么一段话:

  

   简单的说,就是不让有长跳转动作,其实这两种都对,intel手册上说的是让BIOS在高地址空间运行,器件一直修改CS寄存器,也就是一直使用Base+EIP的方式生成地址,这种新式方法应该是UEFI的,那种刚开始就长跳转的属于老式做法。

  假设有一块1M的flash芯片,第一条指令一般都是在0xFFFF0的这个位置,这样的原因,我们可以很简单的想到,这是为了把这1M空间方便的映射到4G地址中最高的1M中吧,可能看起来比较对齐吧。

  BIOS也就是ROM的地址空间通过CPU的硬件自动映射到了高地址1M,但是我们平时看到的都是低于1M的BIOS,因为在高地址的时候,CPU实际上是在访问ROM,这段时间内,基本的操作就是硬件初始化,最重要的肯定是RAM等重要硬件的初始化,初始化完成后,CPU根据BIOS中的“搬家”代码,回将ROM的所有内容拷贝到RAM中(整体拷贝比较方便,如果是想着把前面执行过的剔除掉,得不偿失),当然这个位置肯定就是低1M的地址空间,比如上图中,从0xF0000开始的那64Kb空间(放心,一般的BIOS不会超过64KB),拷贝完成后,CPU会执行一条长跳转,这会引起CS寄存器的改变,也就会控制CPU指向RAM进行执行程序了,这样带来2个好处,第一肯定是RAM比ROM更快,第二是这样重新满足了实模式下寻址范围是1M的这一特点,当然CPU寻址方式回重新回归到CS左移4位+IP的模式。

  到这里还有一些疑问:我们一般会认为第一条紫菱本身就是一条长跳转指令,那么CPU是怎么完成内存初始化后,并将BIOS相关数据拷贝到1M以下地址空间呢?这里有几种可能(方便说服内心的猜测),第一是这条指令并不是真正的长跳转,而是先进行一些基本的初始化,才跳转,第二是ROM到地址空间的映射并不是简单的映射到搞地质的1M,而是有着更复杂的映射方式,使得长跳转后时间上CPU还是在访问ROM,第三就是CPU一旦上电,就自动的由硬件将BIOS内容复制到对应的RAM中,这一点在ARM9的工作模式可以验证。

  

电脑CPU开机上电后的第一条指令的更多相关文章

  1. postgresql分组后获取第一条数据

    -- 根据编号分组取第一条数据 select * from table t where t.no=(select max(no) from table t1 where t1.no=t.no) -- ...

  2. 自己动手写处理器之第四阶段(1)——第一条指令ori的实现

    将陆续上传本人写的新书<自己动手写处理器>(尚未出版),今天是第11篇,我尽量每周四篇 第4章 第一条指令ori的实现 前面几章介绍了非常多预备知识,也描绘了即将要实现的OpenMIPS处 ...

  3. oracle获取排序后的第一条信息

    查询表table1里字段id小于10的所有数据,并且让数据根据id降序排列,然后得到第一条数据 select * from (select * from table1 where id<10 o ...

  4. sqlserver 数据库分组后取第一条数据

    分享一个朋友的人工智能教程.零基础!通俗易懂!风趣幽默!大家可以看看是否对自己有帮助,点击查看教程. 比如查询用户某一天最后一笔交易后的账户余额 SELECT *( SELECT *, row_num ...

  5. oracle排序后的第一条记录

    该查寻语句没有经过任何的优化,因为oracle没有SQL的TOP关键字,但是有一个ROWNUM的列,因此,可以通过ROWNUM来进行查询.oracle的关于rownum的参考手册里面提到了    分析 ...

  6. SQL group by 分组后,同一组的排序后取第一条

    SELECT * FROM(                SELECT                     [SPID]                    ,[PH1]           ...

  7. 王爽《汇编》检测9.1(1) | 若要使程序中的jmp指令执行后,CS:IP指向程序的第一条指令,在data段中应该定义哪些数据?

    ;监测点9.1(1) assume cs:code data segment db dup() data ends code segment start: mov ax,data :这一段一定要补上 ...

  8. MSSQL 分组后取每组第一条(group by order by)

    查询中经常遇到这种查询,分组后取每组第一条.分享下一个SQL语句: --根据 x 分组后.根据 y 排序后取第一条 select * from ( select ROW_NUMBER() over(p ...

  9. Linux 从头学 01:CPU 是如何执行一条指令的?

    作 者:道哥,10+年的嵌入式开发老兵. 公众号:[IOT物联网小镇],专注于:C/C++.Linux操作系统.应用程序设计.物联网.单片机和嵌入式开发等领域. 公众号回复[书籍],获取 Linux. ...

随机推荐

  1. spark-client 一直 accepted,无法提交任务,报错Failed to connect to driver at

    这个问题的原因有几个: 1.客户端安装的机器一般是虚拟机,虚拟机的名称可能是随便搞的,然而,yarn-client模式提交任务,是默认把本机当成driver的.所以导致其他的机器无法通过host的na ...

  2. spring学习笔记 星球日one - xml方式配置bean

    ide: idea lib包的导入:http://webcache.googleusercontent.com/search?q=cache:http://zyjustin9.iteye.com/bl ...

  3. Flutter - 左右侧滑菜单:drawer和endDrawer

    侧滑菜单可以从左面滑出,也可以从右面滑出.在Scaffold中有drawer和endDrawer两个参数,分别对应左边的菜单和右边的菜单. drawer: new Drawer( child: new ...

  4. java学习(一) 环境搭建、hello world的demo

    本程序媛搞前端的,上班偶有空闲,不妨来学习学习,不然怎么包养小白脸,走上人生巅峰? 说实话,每个语言都相通,有了javascript的基础,并且有了两三年跟java打交道的经验,简单学习下java想必 ...

  5. 模块化开发之butterknife 在 library中使用

    在Android开发中butterknife是一个很好的对资源初始化的工具,它可以使你的代码简洁通俗易懂,同时配合Android ButterKnife Zelezny插件可以让你写代码的速度提升至少 ...

  6. websocket protocal

    same-orgins:浏览器同源策略的安全模型   持久化协议   双向双工  多路复用, 同时发信息   区别HTTP连接特点:  http只能由客户端发起,一个request对应一个respon ...

  7. RobotFramework测试环境搭建记录

    Robotframwork测试环境搭建记录 1.安装Python2.7(https://www.python.org/) 在环境变量path中加入“C:\Python27” 安装后的验证方法为在命令行 ...

  8. scrapy的简单使用

    使用之前的创建虚拟环境方法(pipenv) 创建虚拟环境并进入虚拟环境 mkdir douban cd douban pipenv install pipenv shell 再安装我们的scrapy ...

  9. python初学者随笔Week2

    一.集合 去重,把一个列表变成集合,自动去重 关系测试,测试两组数据的交集,并集,差集关系 集合是无序的 集合的操作: list_1 = [1,4,5,7,3,6,7,9] list_1 = set( ...

  10. Redis勒索事件爆发,如何避免从删库到跑路?

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云数据库 TencentDB发表于云+社区专栏 9月10日下午,又一起规模化利用Redis未授权访问漏洞攻击数据库的事件发生,此次 ...