X86 第一条CPU指令及BIOS Shadow

目录

一、CPU第一条指令计算

二、找到第一条指令所在位置

三、第一条指令的内容   

四、BIOS Shadow


一、CPU第一条指令计算

         开机时CPU进入实模式,8086以及80286的寻址方式为段寄存器左移4位+偏移地址(IP中的值)。第一条指令为FFFF0h,位于1M字节的往下第16个字节的地方。而到了80386,段寄存器由一个段选择子、基地址、长度和访问属性构成(80286就有了,不过是一个过渡阶段,还是以386为主,资料记载比较多),无论是在实模式还是在保护模式下,访问物理内存的方法都是段寄存器中隐藏部分的段基址与EIP相加得到的地址。

        80386 CPU在保护模式下由段选择子在段描述符表中取出基地址,然后放到CS寄存器中隐藏部分的段基址中,再和EIP偏移地址相加得到(下次直接从隐藏寄存器中取出相加即可,提高速度)。在实模式下,则是由16位的段选择子左移4位写入到副本寄存器中基地址,再由此基址和IP相加得到,后续程序只需要使用Jmp IP指令,CPU直接从副本寄存器中的基地址取出与IP作相加运算即可,无需在使用CS左移4位的方式,来提供速度。

        而一种比较特殊的情况是在80386 CPU复位的时候,隐藏寄存器中的段基址被初始化为FFFF0000h,直接和EIP(FFF0h)相加则得到了第一条指令地址0xFFFFFFF0。实模式下,本来只能访问1M的物理空间,而现在却到了4G-16字节处,显然超出了实模式的1M寻址范围限制,其内部电路强行把FFFF0000写入到了隐藏寄存器中的段基址,当代码第一次尝试修改CS寄存器后,CPU的寻址范围才会被限制在1M以内。

8086(16位CPU)

80286(16位CPU)

80386(32位CPU)

CS寄存器

16位

16位

(有资料显示,这个时候的段寄存器已经有包含隐藏部分了,具体内容没有查到,访问的时候,也是先载入到隐藏部分的基址寄存器中。)

总长96位

16位可见部分:段选择子

80位不可见部分(描述符缓存“descriptor cache”或隐藏寄存器“shadow register”):32位基地址+32位长度+16位属性

复位时CS:IP

FFFF:0

F000:FFF0

F000:FFF0(基址:FFFF0000h 长度:FFFFh  EIP:0000FFF0h)

第一条指令地址

FFFF<<4+0=FFFF0

F000<<4+FFF0=FFFF0

FFFF0000+FFF0=FFFFFFF0

地址线宽度

20(最大寻址2^20=1M字节)

24(最大寻址2^24=16M字节)

32(最大寻址2^32=4G字节)

数据线宽度

16

16

32

二、找到第一条指令所在位置

        80386第一条指令地址为0xFFFFFFF0,位于CPU物理地址4G空间倒数第16个字节中。在CPU上电的时候,CPU发送此地址到北桥上解码,如果该地址没有被北桥上的设备占用,那么就会通过DMI通道发送到南桥上的设备进行解码,此地址会被南桥的SPI控制器接收并通过SPI访问BIOS 芯片。

        北桥芯片中的PAM0-6(Programmable attribute map)寄存器,它可以将DRAM映射到C、D、E、F的这四个段设置为只读,只写,可读可写,关闭的属性。如通过PAM0将0F0000-0FFFFF段设置为只写,那么当读取0xF1234地址内容时,北桥芯片将此地址传送到PCI域,最后解码到BIOS 芯片上。下图为Intel 430tx北桥芯片组的PAM寄存器。

 

 

  

 

三、第一条指令的内容   

        80386第一条指令内容是一个长跳转指令,有的BIOS IBV这条指令是 Jmp F000:E05Bh,有的则是Jmp F000:FFAAh。不同产商做法不同,都是一条长跳转指令。CS将被更新成0xF000,表面上看CS其实没变化,但CS的基址域将被更新为0x000F0000h(0xF000左移4位),此时形成的物理地址为Base+EIP=0x000FE50B,而此地址是在1M中的了。0xFFFE0000-0xFFFFFFFF和0xE0000-0xFFFFF这两段物理地址均是会被decode到BIOS 芯片中。

四、BIOS Shadow

        为了提高性能,BIOS把BIOS image的内容拷贝到DRAM中,这个过程叫做BIOS Shadow,  该处的DRAM称为Shadow memory。如下图所示,一开始是直接在BIOS芯片上读取数据,是相当慢的,当内存初始化后,BIOS把ROM中的数据拷贝到低端内存中(如第1和2段)运行,然后对2段(对应下图左的E段)中包含整个BIOS的代码进行解压放到第5和6段,再将其拷贝回内存的E段和F段,再通过PAM寄存器将E段和F段设置为只读,读取时则是访问DRAM域了,这样后面直接就可以在内存中访问legacy BIOS代码了。

 

[参考文献]

1.地址空间映射https://www.cnblogs.com/wudibuzaijia/p/8512712.html

2.[我所知道的BIOS]->[Shadowing] 8

https://blog.csdn.net/ymzhou117/article/details/7081655?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-4.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-4.control

3.Intel 430T数据手册https://www.docin.com/p-1015959013.html

4.《BIOS技术研发剖析》3-2

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值