intelx86为何从0xFFFF0处执行
第一条指令的地址
在用户按下计算机电源开关之后,CPU会自动的将其CS寄存器设定为0xFFFF,将其IP寄存器设定为0x0000。由于CS:IP指出了下一条指令的地址[1],因此CPU会跳到0xFFFF:0x0000处进行执行。为什么是这个地址而不是其它地址呢?这其实是一个很巧妙的设计。
我们知道,从80386开始,到后面80486、奔腾,它们都是32位的CPU,但是它们都与Intel先前开发的8086兼容。也就是说,在默认情况下,80386、80486等,只不过是一台运行得更快一些的8086罢了。因此,这里我们只讨论8086[2]。
8086是16位的CPU,但是却有20根地址线[3]。也就是说它可以寻址 220 = 1M 内存空间。这段内存空间由RAM、ROM组成。ROM是随机只读存储器,里面的程序是在计算机出厂的时候直接烧录在里面的,完成一些主机自检等操作,并提 供一些访问磁盘等基本输入输出服务,因而这段程序常被称为BIOS(Basic Input/Ouput Service)。由于不同的计算机厂商生产的计算机所带的外设不一样,因此,这段程序大小也限机型的不同而不一样,有可能A厂出产的计算机所带的这段程 序的大小为1K,而B厂出产的这段程序的大小为2K。如果将这段程序放在0x0000处,那么用户写的程序就可能从0x0400处开始也可能从 0x0800处开始,非常不统一。故而,将此段程序放在1M内存的顶部,那么用户写的程序就都可以从0x0000处开始了。
但将BIOS这段程序放在1M内存的顶部,如果这段程序大小为1K,那么应当从0xFFC00开始放。如果这段程序的大小为2K,那 么应当从0xFF800开始放,对于CPU而言,到底是应当从0xFFC00开始执行还是应当从0xFF800开始执行呢?为了解决这个问题,8086规 定,CPU均从0xFFFF0处开始执行,而在0xFFFF0处,放一条无条件转移指令JMP。如果A厂的BIOS是从0xFFC00开始放的,那么这条 转移指令就跳转到0xFFC00处开始执行。如果B厂的BIOS是从0xFF800开始放的,那么这条转移指令就跳转到0xFF800处开始执行,各个厂 家可以跟据自己所生产的BIOS程序的大小,来决定此转移指令具体跳转到的位置。
这里有一点需要清楚的是,通常认为,内存编址是连续的,不会出现空洞,其实完全不是这样。比如,假设BIOS的编址是从 0xF0000开始,而RAM,即通常讲的内存编址是从0x00000开始,那么,如果用户只安装了32K内存,那么内存的编址范围就是 0x00000~0x07FFF,那么从0x08000至0xEFFFF处就没有安装内存,这就是一个内存空洞。
好了,当CPU执行了放在0xFFFF0处的第一条指令后,就跳转到BIOS程序内部去执行了,下面就来看看BIOS都做了些什么。
BIOS的工作
BIOS的工作相当简单,主要的工作就是执行主机自检(POST),然后查找操作系统存在在哪个磁盘上,将操作系统载入。BIOS在查找各磁盘 的操作系统时,主要是查找磁盘上的第一个扇区(0面0磁道1扇区),每个扇区是512字节,如果这是一个引导扇区,那么就将它载入0x7C00的内存地址上,然后跳转到此地址上执行。如果此不是一个引导扇区,就继续查找下一个磁盘,看其上面是否存在引导扇区。如果所有的磁盘上都不存在引导扇区,则在屏幕上 打印出一条出错信息。
引导扇区的工作
引导扇区只有一扇区即512字节大,因此它的主要目的是把操作系统的内核读进内存,然后跳转到操作系统内核处开始执行。从编写操作系统角度来 说,前面的CPU上电及BIOS的工作都不是操作系统能控制的,而从引导扇区开始,就完完全全可由操作系统来控制了,因此,编写引导扇区也是编写操作系统 必要的工作之一。从BIOS跳入引导扇区后,计算机系统引导工作就算完成,怎样把操作系统内核读进内存,然后再安排一条跳转指令跳到内核处执行就是操作系 统开发人员的工作了。
intelx86为何从0xFFFF0处执行的更多相关文章
- C语言实现程序跳转到绝对地址0x100000处执行
嵌入式笔试题:想让程序跳转到绝对地址0x100000处执行,该如何做? 请详细解释一下所给的答案: 网上看到有如下答案: *((void(*)(void))0x100000)(); 经过在VC++6. ...
- 【Node.js】Event Loop执行顺序详解
本文基于node 0.10.22版本 关于EventLoop是什么,请看阮老师写的什么是EventLoop 本文讲述的是EventLoop中的执行顺序(着重讲setImmediate, setTime ...
- Java Main如何被执行?(转)
java应用程序的启动在/hotspot/src/share/tools/launcher/java.c的main()函数中,而在虚拟机初始化过程中,将创建并启动Java的Main线程.最后将调用JN ...
- erlang虚拟机代码执行原理
转载:http://blog.csdn.NET/mycwq/article/details/45653897 erlang是开源的,很多人都研究过源代码.但是,从erlang代码到c代码,这是个不小 ...
- mysql 批处理命令执行多个sql脚本
方法1 若有SQL脚本a.sql, b.sql, 其目录在f盘根目录下, 则可再写一个SQL脚本c.sql(假设其目录也在f盘根目录下, 也可以在其他路径下)如下: source f:/a.sql; ...
- Java Main如何被执行?
java应用程序的启动在在/hotspot/src/share/tools/launcher/java.c的main()函数中,而在虚拟机初始化过程中,将创建并启动Java的Main线程.最后将调用J ...
- [WEB安全]无回显代码执行【转载】
原作者:AdminTony 原文链接:http://www.admintony.com/无回显代码执行利用方法.html 在Root-Me上有一道代码执行的题目,其链接为题目链接 0x01 简介 打开 ...
- python函数的执行过程
对于 Python 常规函数,都只有一个入口,但会有多个出口如 return 返回或者抛出异常.函数从入口进入会一直运行到 return 语句或者抛出异常,中间不会暂停,函数一直拥有控制权.当运行结束 ...
- linux 驱动学习笔记03--Linux 内核的引导
如图所示为 X86 PC 上从上电/复位到运行 Linux 用户空间初始进程的流程.在进入与 Linux相关代码之间,会经历如下阶段. ( 1 ) 当系统上电或复位时, CPU 会将 PC 指针赋值为 ...
随机推荐
- 多测师讲解性能测试_面试题_001高级讲师肖sir
什么叫做性能测试?1. 软件的性能是软件的一种非功能特性,它关注的不是软件是否能够完成特定的功能,所以一般来说性能测试介入的时机是在功能测试完成之后.另外,由定义中的及时性可知性能也是一种指标,可以 ...
- ngx_align 值对齐宏
ngx_align 值对齐宏 ngx_align 为nginx中的一个值对齐宏.主要在需要内存申请的地方使用,为了减少在不同的 cache line 中内存而生. // d 为需要对齐的 // a 为 ...
- linux(centos8):firewalld使用ipset管理ip地址的集合
一,firewalld中ipset的用途: 1,用途 ipset是ip地址的集合, firewalld使用ipset可以在一条规则中处理多个ip地址, 执行效果更高 对ip地址集合的管理也更方便 2 ...
- ABAP分享十: 文件的上传 方法一
前提条件:PARAMETERS P_files TYPE RLGRAP-FILENAME. AT SELECTION-SCREEN ON VALUE-REQUEST FOR P_files.一.文件的 ...
- Java接口的初始化
背景 接口与类真正有所区别的是前面讲述的四种"有且仅有"需要开始初始化场景中的第三种:当一个类在初始化时,要求其父类全部都已经初始化过了,但是一个接口在初始化时,并不要求其父接口全 ...
- 如果只推荐一本 Python 书,我要 Pick 它!
今年二月初,我偶然看到了一条推特: <流畅的Python>一书的作者发布了一条激动人心的消息:他正在写作第二版! 如果要票选最佳的 Python 进阶类书目,这本书肯定会是得票率最高的书籍 ...
- 学习python须知,Python基础进阶需掌握哪些知识点?
Python基础进阶需要掌握哪些知识点?Python将是每个程序员的标配,有编程基础再掌握Python语言对于日后的升职加薪更有利.Python语言简洁利于理解,语法上相对容易能够让开发者更专注于业务 ...
- C#之txt的数据写入
一.背景 小伙伴们在使用C#开发时,可能需要将一些信息写入到txt,这里就给大家介绍几种常用的方法. 二.思路 2.1将由字符串组成的数组写入txt 此种方法不需要使用Flush和Close(). 如 ...
- python识别视频黑屏或者低清晰度
第一步:获取视频第一帧图片 https://www.cnblogs.com/pythonywy/p/13749735.html 第二步:进行识别 import os import numpy as n ...
- 没事学学KVM(二)创建一台虚拟机
首先通过VMware创建一台虚机,建议内存大于1G,并开启CPU 的inter vt-x功能,安装好对应的软件后,yum install -y qemu-kvm* virt-* libvirt* 准备 ...