结合上面的文章,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. MFC 消息映射、分派和传递

    几个重要的结构体: struct AFX_MSGMAP { AFX_MSGMAP* pBaseMessageMap; AFX_MSGMAP_ENTRY* lpEntries; } struct AFX ...

  2. 【HNOI2014】画框

    题面 题解 这又是一种套路啊233 将\(\sum a_i\)和\(\sum b_i\)分别看做\(x\)和\(y\),投射到平面直角坐标系中,于是就是找\(xy\)最小的点 于是可以先找出\(x\) ...

  3. 【LG3246】[HNOI2016]序列

    [LG3246][HNOI2016]序列 题面 洛谷 题解 60pts 对于每个位置\(i\),单调栈维护它往左第一个小于等于它的位置\(lp_i\)以及往右第一个小于它的位置\(rp_i\). 那么 ...

  4. P5231 [JSOI2012]玄武密码

    P5231 [JSOI2012]玄武密码 链接 分析: 首先对所有询问串建立AC自动机,然后扫描一遍母串,在AC自动机上走,没走到一个点,标记这个点走过了,并且它的fail树上的祖先节点也可以访问到( ...

  5. 扩展gcd算法

    扩展gcd算法 神tm ×度搜索exgcd 打到exg的时候出来ex咖喱棒... 球方程\(ax+by=\gcd(a,b)\)的一个解 如果\(b=0\),那么\(\gcd(a,b)=a\),取\(x ...

  6. IDEA/Git 设置多个push远程仓库或者同时提交多个push仓库

    注:写在最上面的这个提交地址将会是唯一的pull地址 具体解决办法: 在隐藏文件.git 下有个config文件,打开,在最后一行添加以下信息 [remote "all"] url ...

  7. nginx配置转发详解

    nginx各项参数的详细配置 本文主要讲解nginx.conf中server部分配置及多路转发问题: server { listen 9090; server_name 127.0.0.1; #cha ...

  8. Apache和Nginx比较

    Apache和Nginx对比 功能对比 Nginx和Apache一样,都是HTTP服务器软件,在功能实现上都采用模块化结构设计,都支持通用的语言接口,如PHP.Perl.Python等,同时还支持正向 ...

  9. Unity3d — — UGUI之Box Collider自适应大小

    NGUI下给Sprite/image添加collider后能自适应大小,但是在UGUI下Collider是默认在(0,0)位置,size为0 因此写了个简单的脚本,效果如下(最后附代码) 1.如下图添 ...

  10. Azure-如何排查应用程序网关返回 HTTP Code 502 或客户端得到应用程序网关响应慢的问题(二)

    问题描述 经过如何排查应用程序网关返回 HTTP Code 502 或客户端得到应用程序网关响应慢的问题(一)中的排查步骤,可以判断出是由于 Web 服务器自身问题导致的响应异常. 那么可以在 IIS ...