CPU执行第一条指令时情形

CPU加电后第一条指令 当我们按下电源开关时,电源就开始向主板和其它设备供电,此时电压还不太稳定,主板上的控制芯片组会向CPU发出并保持一个RESET(重置)信号,让 CPU内部自动恢复到初始状态,但CPU在此刻不会马上执行指令。当芯片组检测到电源已经开始稳定供电了(当然从不稳定到稳定的过程只是一瞬间的事情),它便撤去RESET信号(如果是手工按下计算机面板上的Reset按钮来重启机器,那么松开该按钮时芯片组就会撤去RE 阅读详情

CPU执行第一条指令时情形

 

cpu执行的第一条指令不在内存中,众所周知,内存是由ram组成的 ,而ram不断电,可以保存信息,一旦断电,ram中的信息将会丢失,所以cpu要执行的第一条指令被固化在rom中。

以前8086年代,由于内存是1M的,所以rom被编址在1M的最后的64K中,所以它的段地址是0xFFFF0,这样就不至于不ram分成两个部分,就是将cs设置成0XF000,cpu执行的BIOS第一条指令的地址是:0XF000:FFF0H,这样使得固件的地址在寻址空间靠后的位置16个字节处,这是一条跳转指令,向前调转到一个地方,然后开始执行,启动代码由jmp F000 : XXXX中的偏移XXXX来把握,如果使用得多,XXXX就小,使用得少,XXXX就大,这样使启动代码尽量靠后,而不浪费多余的地址空间,由于地址空间安排在最后,也不会把整个地址空间隔离成两段。

而出现80386以后,内存已经大于1M,所以如果把冷启动固件编址在F000h段内,就会把整个地址空间隔离成不连续的两段,一段是F000h以前的地址,一段是1M以后的地址,这很不方便。Intel采用的办法是,还是默认将执行启动代码的BIOS ROM编址在系统可寻址空间的最后(如32位x86机的话,这段地址就位于4GB的最后一个64K内),在系统复位时,CPU进入实模式,并将CS寄存器设置成F000h,而将它的shadow register的Base设置成FFFF0000h(理论上正常情况下CS为F000h的话,其shadow register的Base应该设置成000F0000h,但intel有意识的将高12位触发成1了,除了这样他也没有什么好办法让机器一启动就跑道4GB那么高的地址上去执行),而偏移量EIP置成0000FFF0h,所以机器执行的第一条指令的固件安排的物理地址显然就变成了FFFFFFF0h。BIOS代码和以前还是要兼容的,也就是说此时从FFFFFFF0h处取出的还是一条远跳转指令jmpF000 : XXXX(我跟踪调试过好几款BIOS,这里的XXXX似乎都是E05B),问题随之而来。这个远跳转指令是要更新CS寄存器和它的shadowregister的,也就是说执行这条jmp F000 : E05B之后(也就是CPU执行第一条指令之后),CS将被更新成F000,其实CS原来就是这个值,这里说不上是更新,但CS的shadowregister就不一样了,它被真正的更新了,它的Base域被更新成000F0000h了(高12不再具有触发成1的功能,那个功能只在机器启动到第一次更新CS的内容期间有效)。这个Base再加上虚拟地址中的偏移量E05B,得到物理地址000FE05Bh,这就是CPU执行的第二条指令的地址,但是这条指令的地址已经是1M以内了。但我们不要忘记,这时的F000h段内可不再是BIOS ROM了,这一段此时安排的事实上是我们的RAM空间,这一段RAM需不需要初始化才能使用那还另说,关键是此时此刻这个地方不应该有可以执行的代码才对啊?CPU第二条指令就跳到这里不是自寻死路吗?

似乎走进了死胡同,但我翻阅了很多资料,找到了一点线索。在很久以前出现过一个叫着Chips & Technoloqies的公司,他设计出一组被称着neat的芯片组,可以将内存高端的BIOS ROM映射到1M以内的RAM空间里,并且可以使这一段被映射的RAM空间具有与ROM类似的只读属性。这个公司后来被intel收购。但后来这种映射似乎就成为了一种标准。由于这种映射关系我们有理由相信,机器启动的时候,4G的最后一个64K里与1M的最后一个64K里应该具有相同的东西,所以即使从FFFFFFF0h用一条jmp跳到000FE05Bh,也仍然能够找到正确的代码去执行。

那么BIOS接下来要干一些什么事呢?它有很多事情要做,我只举几件有代表性的,其中有两件事是DRAM的初始化和memorysizing。按理说这个时候CPU还处在实模式下,BIOS还没有办法去确定超过1M的内存量。另外还有一件事就是代码和数据拷贝,因为映射到1M以内来的BIOSROM容量有限,事实上还有很大一部分没有映射过来,以压缩的形式存放在高端的ROM中了,BIOS在1M以内执行初始化时难免需要将高端的那些内容拷过来使用,这也是不容易做到的。但不要忘了,我们可以使用前面说的将段break成4G的方法来做成这几件事。当然,似乎还存在着这样一种可能性,那就是切换到保护模式,这些事情就都可以做了,并且好像没有必要再切换回实模式。情况没有想象中那么简单,从我前面的那个实验看,我切换到保护模式之后只执行了几行非常必要的将段break成4G的代码,其他的事情一律不做,因为保护模式下有非常严格的特权检查,并且需要设置GDT,IDT,LDT等一系列的表格,一般的代码是不容易在保护模式下跑起来的,所以想在保护模式下完成整个BIOS的初始化,工程过于浩大,几乎等于写一套小型的保护模式操作系统了(FreeBios可能就是这么干的)。

当然我也有足够多的证据证明我们常用的BIOS都使用了这种breaklimit的技术,并且它们完成break后都是迅速切换回实模式。

 

---------------------------------------

 

参考了X86 CPU在段式管理下的地址形成机制以及BIOS初始化过程对这种机制的利用

                   陈英豪  中科院计算所

 

 

 

对于BIOS的一些质疑解答:

 

1.      而这里之后我开始不明白了。JMP要跳转到的位置是在高地址(4G末端)Flash Rom BIOS中还是在低地址(1M末端)的shadow BIOS呢?

2.位于低地址(1M处)的(BIOS shadow)是从Flash BIOS拷贝而来呢,还是没有任何拷贝过程仅仅利用地址映射到原Flash BIOS中的呢?

3.  无论是拷贝还是映射,内存地址空间上ROM BIOS映射区只有 0xF0000~0x100000之间的64KB。而ROM本身有可能大于2M。那映射的应该是原BIOS程序的一部分,那么是哪一部分呢?

 

对这些问题的回答需要阐明机关概念:

1.     机器加电时,内存控制器还没有初时化,内存是不可用。(李皓:这是对的)

2.  机器加电时,对CPU的指令的解码不是北桥,CPU发出的地址被传递到南桥并由FHW (Firmware Hub)解码到BIOS ROM芯片(Flash)。在加电时一直到引导进程初,BIOS的E段(0xE0000~0xEFFFF)和F段(0xF0000~0xFFFFF)和4G内存顶端的对应段0xFFFE0000 ~0xFFFEFFFF和0xFFFF0000 ~0xFFFFFFFF都被FWH解码到BIOS的ROM芯片的两个64区域。即在启动阶段访问0xE0000~0xEFFFF和0xFFFE0000~0xFFFEFFFF是同一个BIOS区域,访问0xF0000~0xFFFFF和0xFFFF0000~0xFFFFFFFF是同一个BIOS区域。

3.     机器加电时,CS段寄存器值为0xF000,EIP值为0x0000FFF0,但CPU的取的地址是段寄存器不可见的部分(影子寄存器)加上偏移部分,此时影子寄存器的值为0xFFFFFFF0。所以CPU执行的第一条指令是0xFFFFFFF0(复位向量),通常在BIOS ROM对应的指令是一个跳转指令JMP F000:E05B,当取出跳转完成后,由于CS段的影子寄存器刷新并重新加载,下一条指令地址是0xFE05B。不过这条指令仍然从BIOS ROM里取得。

4.     关于shadow BIOS,BIOS程序通常是压缩的,在系统初始化阶段,BIOS会解压BIOS Image到RAM中,然后编程北桥控制器对0xE0000~0xFFFFF置为write only,这样对该区域的写被传递到DRAM里,然后把解压的BIOS拷贝到E段和F段。最后重新编程北桥控制器对0xE0000~0xFFFFF置为read only。对于PCI ROM BIOS,BIOS会把每个卡上的ROM拷贝到0xC0000~0xDFFFF然后执行他们的初时化代码。

5.     BIOS ROM可以很大,但不都是可执行的,如含有ACPI Table等,开始解压到0xE0000~0xFFFFF只是其中一部分,在启动过程中还需要从BIOS ROM解压代码到RAM中,并覆盖其中不需要的代码。这个就好像BIOS ROM是硬盘(不过可用直接访问),真正执行的代码在RAM中一样。硬盘可以很大但RAM小,这也就是程序的局部性原理。

证明CPU指令是乱序执行的 单线程的情况下,2个指令乱了顺序执行没有关系,反正最终的结果是一样的,但是在多线程的情况下,非常有可能出现你不想看到的情形,比如x=0、y=0的情况,比如在预知中没有这种情况,但是多线程的情况下,会出现,所以一定会影响整个多线程程序的运行,单线程的程序不会影响。这两种是乱序执行的排列组合,比如第一个场景是线程1先执行x=b、线程2执行y=a,切换到线程1执行a=1,切换到线程2执行b=1,结果是x=0、y=0。第一种组合先执行a=1、x=b,后执行b=1、y=a,得到的结果是x=0、y=1。 阅读详情

相关推荐

8086CPU中14个寄存器的详解

CPU中的寄存器 在执行单元EU和总线接口单元BIU中一共有14个寄存器,其中通用寄存器8个、标志寄存器FLAGS一个、控制寄存器5个。 通用寄存器 8个通用寄存器再进行细分,又可划分为数据寄存器(AX~DX)、栈顶指针寄存器(SP)、基址寄存器(BP)、DI(目标变址寄存器)、SI(源变址寄存器)。 1. 数据寄存器(AX、BX、CX、DX) 16位的数据寄存器可以拆成2个8位寄存器(例如:AX->AH+AL等)来使用,但是一定要注意“8086为16位寄存器,8位寄存器中存放的一定是数

超级霸霸强的博客 2万+

PC加电后,CPU如何执行第一条指令

问题:CPU是如何执行第一条指令的? 小问题:8086年代,为什么第一条指令的位置在F000H:FFF0H? 小问题:为什么第一条指令放在ROM中? 带着这些问题,我开始对cpu执行第一条指令开始研究。 加电后的启动流程 CPU首先会进行硬件初始化(hardware reset)。 然后是可选的自检过程(BIST built-in self-test)。 CPU开始执行第一条指令。从此开始CPU进入软件初始化过程。 在处理器的众多的引脚中,有一个RESET,由于接受复位信号,没当处理器加电,处理器都会执

weixin_43742894的博客 4020

Cisco Packet Tracert 无线路由器配置

Cisco Packet Tracert 无线路由器配置

yushan_caoyu的博客 2万+

计算机基础 -- CPU执行的第一条指令

UEFI是计算机初期为了初始化硬件设备、为OS运行创建合适环境所固化在flash上的一段代码。CPU是计算机的大脑,是整个系统运转的核心,那么是不是计算机一上电,CPU就开始执行UEFI的代码?

学习记录 2655

【DIY】使用STM32及PID算法实现一个磁悬浮玩具

今天教大家来做一个磁悬浮玩具。

小白白学电子 1万+

后仿真中《SDF反标必懂连载篇》之 <INTERCONNECT/IOPATH> 到底反标电路路径是哪里

对于SDF INTERCONNECT ENTRY 描述,我们在之前的文章有详解。读万卷书,行万里路。实践很重要。今天,搞一下SDF INTERCONNECT / IOPATH 延迟数据信息,究竟反标的是哪一路径延时?究竟在电路上一段段如何表现出延迟现象的呢?

那么菜的博客 2138

X86 第一条CPU指令及BIOS Shadow

目录 一、CPU第一条指令计算 二、找到第一条指令所在位置 三、第一条指令的内容 四、BIOS Shadow 一、CPU第一条指令计算 开机时CPU进入实模式,8086以及80286的寻址方式为段寄存器左移4位+偏移地址(IP中的值)。第一条指令为FFFF0h,位于1M字节的往下第16个字节的地方。而到了80386,段寄存器由一个段选择子、基地址、长度和访问属性构成(80286就有了,不过是一个过渡阶段,还是以386为主,资料记载比较多),无论是在实模式还是在保护模式下,...

weixin_43858632的博客 3313

全志T527 适配双目tp2815_mipi

在全志T527 linux下适配双目TP2815 mipi摄像头,支持六路同时输出,四路可用作360环视、一路face id等,一路用于其它开发。

Linux驱动开发工程师,熟悉Linux/Android底层驱动、TP、显示、IIC、网络等通用外设调试适配,Linux上层应用开发。常用平台瑞芯微、全志、恩智浦等。 3822

计算机开机执行的第一条指令是什么?

第一条指令的位置在FFFF:0000,也就是物理地址FFFF0。第一条指令是跳转到F000:EO5B。 接下来准备由实模式进入保护模式。加载GDT,置PE位为1,清指令预取队列并真正进入保护模式。 那么计算机一直更新换代,这种模式是如何一直保持兼容的呢? 追溯到最早 808X 系列处理器,8080 是 16 位 address bus, 8086 及 8088 改进为 20 进 addres...

weixin_30294709的博客 2731

通过WorkVisual连接KUKA机器人的具体方法

通过WorkVisual连接KUKA机器人的具体方法

Robot_PLC_HMI_Automation 6845

【AI大模型】核心基石:Transformer架构入门通俗完整解读

文章摘要: Transformer架构是AI大模型(如GPT、Llama等)的核心基石,彻底颠覆了传统RNN/LSTM的逐字计算模式,通过自注意力机制实现全局并行运算和长文本语义理解。本文用通俗语言拆解Transformer的核心模块:位置编码保留语序、多头注意力捕捉上下文关联、掩码机制确保生成逻辑、残差连接稳定训练,并搭配极简PyTorch代码演示Decoder架构的逐字生成过程。Transformer的并行性、可堆叠性和全局注意力优势,使其成为千亿参数大模型的基础。理解Transformer是掌握大模型

unber的博客 44

cpu执行第一条指令时情形

cpu执行的第一条指令不在内存中,众所周知,内存是由ram组成的 ,而ram不断电,可以保存信息,一旦断电,ram中的信息将会丢失,所以cpu要执行的第一条指令被固化在rom中以前8086年代,由于内存是1M的,所以rom被编址在1M的最后的64K中,所以它的段地址是0xFFFF0,这样就不至于不ram分成两个部分,就是将cs设置成0XF000,cpu执行的BIOS第一条指令的地址

933

彻底解决tplink路由器无法访问部分https网站

彻底解决tplink无法访问部分https网站

renkai721的专栏 8766

CPU指令的乱序执行和内存序

单线程的情况下,2个指令乱了顺序执行没有关系,反正最终的结果是一样的,但是在多线程的情况下,非常有可能出现你不想看到的情形。Consume(消费):类似Acquire,但作用仅限当前线程(现代编译器中少用,不做介绍了)。Acquire(获取):保证加载后续的读写操作不被重排到此加载操作前,适用于读取共享数据。的读写是没有数据依赖的,遇上在单线程中不会出问题的指令重排,在多线程中就出现了问题:在。在代码退出的时候调用,先负责把一些还没有发送出去的事件都发送了,再设置。负责消费一些事件,在监听到。

sinat_27652257的博客 526

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

26-计组-指令执行过程

指令周期是CPU执行一条指令所需的完整时间,包含取指(必选)、间址(可选)、执行(必选)和中断(可选)四个子周期。机器周期通常等于访存时间,其数量取决于指令格式和寻址方式。指令执行流程包括:PC指向指令地址→取指→译码→计算操作数地址→执行运算→存储结果。数据流在取指周期表现为PC→MAR→主存→MDR→IR的传输链,间址周期则获取操作数有效地址。中断周期通过调整SP实现断点保护。不同指令的周期长度和操作步骤存在显著差异,核心流程始终围绕"取指-译码-执行"展开。

m0_57856520的博客 1321

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

计算机中CPU、内存、硬盘、指令的的作用以及运行浅析

最近在学习计算机的基本原理和组成,讲自己的学习的一点东西在博客上做一个记录。一、冯诺依曼结构:现在的计算机都是冯诺依曼结构的,根据wiki的定义冯诺依曼的结构如下: 主要由内存、运算+控制(CPU)、输入和输出设备组成。在上图中把 控制单元和逻辑计算单元分开了,其实在现实中都是由CPU来完成的。内存就是平时我们说的内存,看下wiki上的解释,即主存RAM,RAM的几个特点如下: 1. 随机储存

lagelangzhi的博客 2264

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

8086CPU指令系统 串操作指令和处理机控制指令

串操作指令和处理机控制指令小节串操作指令1,常见的串操作指令处理机控制指令1,标志位操作指令2,同步控制指令3,暂停及空操作指令 前言:公号 「编程有料」后台回复 “电子书” 即可获取近1000本助力你编程之路的电子书 串操作指令 什么叫数据串,什么叫串操作呢? 数据串是存储器中一块字节或字的存储区域,其长度可以是1字节一64K字节。 串操作就是对数据串中每个元素所进行的操作,这种操作通常是组合操作,能完成几条指令的功能。 1,常见的串操作指令 1,串传送指令MOVSB/MOVSW 格式:MO

阔码人生 2226

linux下 用cpuid指令读取CPU信息

<br />#include<stdio.h><br /><br /><br />int main()<br />{<br />    unsignedint eflags1, eflags2 = 0;<br />    unsignedint eax = 0;<br />    unsignedint ebx,ecx,edx;<br /><br /><br /><br /><br />    /**<br />     * 测试CPU是否支持CPUID指令。<br />     * eflags寄存器的第

Timmy_zhou的专栏 1万+

CPU性能测试分析MIPS、DMIPS

一 what MIPS: million instruction per second,表示每秒多少百万条指令,如 10MIPS ,表示每秒一千万条指令。 MIPS/MHz : 表示 CPU 在每 1MHz 的运行速度下可以执行多少个MIPS ,如 10MIPS/MHz,表示如果 CPU 运行在 1MHz 的频率下,每秒可执行一千万条指令,如果 CPU 运行在 5MHz 的频率下,每秒可执行五千万...

myselfzhangji的博客 3万+

手搓单周期、流水线CPU

手搓cpu

m0_56695799的博客 3084

CPU 的Cache 和Latency

CPU 速度的进展,一直比记忆体的速度进展要来得快。在 IBM PC XT 的时代,CPU 和记忆体的速度是差不多的。不过,后来 CPU 的速度就愈来愈快。再加上 DRAM 需要 refresh 才能保存资料的特性,DRAM 很快就跟不上 CPU 的速度了。现在的 CPU 都利用了 pipeline 的方式,可以每个 cycle 都 issue 一个(甚至多个)指令,再加上现在的 CPU 时脉也比

DigBug的专栏 6403

Cpu 指令重排序遵循规则 as-if-erial

在单线程情况下,无论如何对指令进行重排序,最后的执行结果是一样的

孙应路的博客 351

单核CPU与多核CPU的区别

1、单核CPU 1.1 工作原理 工作原理:单核CPU较为死脑,在通电时该CPU就会执行存储块中的指定地址的指令,如果你想要执行内存块其他地方的代码必须调整总线位置才可以让其执行。单核CPU就相当于阻塞程序,在工作期间只能执行某一个程序! 每一个CPU都需要有较为独立的电路支持,有自己的Cache,而他们之间通过板上的总线进行通信。 假如在这样的架构上,我们要跑一个多线程的程序,不考虑超线...

zhanghui962623727的博客 2万+

jvm指令重排

JVM会在不影响正确性的前提下调整语句(指令)的顺序。 例如下代码: static int i; static int j; // 在某个线程内执行如下赋值操作 i = ...; j = ...; //可以看到,至于是先执行 i 还是 先执行 j ,对最终的结果不会产生影响。所以,上面代码真正执行时,既可以是 i = ...; j = ...; //也可以是 j = ...; i = ...; 这种特性被称为指令重排,多线程的某些情况下指令重排会影响正确性。 1、为什么会有指令重排这.

baidu_40120883的博客 2084

riscv汇编指令_从零开始学RISCV之初探EXU

从零开始学RISC-V之初探EXU背景介绍有请EXU登台指令译码寄存器文件算术运算指令写回一个又一个的顶层仿真结果及分析总结一下背景介绍EXU主要负责指令的具体执行,一条指令的生命周期,从IFU取指令开始,历经指令解码,执行,写回,访存五个步骤,这其中,除首尾两个步骤由其他模块负责之外,其余步骤均有EXU负责完成。以一个常见的加法指令ADD t5, ra, sp为例,EXU在完成该指令的...

weixin_35664081的博客 1493
上一篇: main函数带参数在VS2008下调试方法
下一篇: Linux及Arm-Linux程序开发笔记(零基础入门篇)
ctrloep
博客等级 码龄19年 4粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值