实验1前篇——BIOS编程空间
Posted yiye_01
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实验1前篇——BIOS编程空间相关的知识,希望对你有一定的参考价值。
从此篇开始更多的注重技术细节了。细节决定成败的故事太多了,而且对于编程者肯定都有这样的经历 —— 自信满满的认为自己写得程序天衣无缝,但是当运行调试之后,才发现bug无处不在,更可气的是很多的bug却是因为语法细节或者指尖上的失误导致。而且编码效率的提升,更多的是建立在已经存在的可信代码的基础上,而可信代码却是经历过无数次的折腾的结晶。实验1的内容是“启动PC系统”——一个从开机到运行到OS的流程;看似一个很复杂的流程,为了很好的解剖这样的流程,需要充分的知识准备,而且更重要的是从代码的角度去解释该过程。所以我们将这一篇的内容定位与介绍一些概念与模拟代码,保证理解过程的顺利。换句话说,如果在理解实验1的内容有什么问题,可以参考该篇给出的内容或者相关资源。
本篇主要通过两个部分来做出详细的介绍:其一为Bios编程空间;其一为C与汇编的互调。
一)BIOS编程空间
这里有一个很陌生的名词——编程空间,其实,这是我对编程环境的一个定义,一般用编程环境来描述,但是它强调的是编码的工具与使用的api等概念;但是用编码空间来代替它,因为它不仅仅包含这些内容,更多的是强调编程时更关心其代码运行的环境(内存空间,处理器状态,外设的资源使用),而且是在一个固定的环境中。
对于BIOS的编程空间,我们关注的点主要有如下几个方面:
1.处理器的状态
寄存器的长度为16位,处于8086的处理器状态,详情参考《64-ia-32-architectures-software-developer-manual-325462.pdf》20.1REAL-ADDRESS MODE
2.内存的使用
内存空间为0-1M的连续空间,地址访问方式为(DS<<4|BX);详情参考《64-ia-32-architectures-software-developer-manual-325462.pdf》20.1REAL-ADDRESS MODE
然而不是1M空间都能被任意使用,所以需要理解内存映像——内存地址区域的实际使用情况:
start | end | size | type | description |
Low Memory (the first MiB) | ||||
0x00000000 | 0x000003FF | 1 KiB | RAM - partially unusable (see above) | Real Mode IVT (Interrupt Vector Table) |
0x00000400 | 0x000004FF | 256 bytes | RAM - partially unusable (see above) | BDA (BIOS data area) |
0x00000500 | 0x00007BFF | almost 30 KiB | RAM (guaranteed free for use) | Conventional memory |
0x00007C00 (typical location) | 0x00007DFF | 512 bytes | RAM - partially unusable (see above) | Your OS BootSector |
0x00007E00 | 0x0007FFFF | 480.5 KiB | RAM (guaranteed free for use) | Conventional memory |
0x00080000 | 0x0009FBFF | approximately 120 KiB, depending on EBDA size | RAM (free for use, if it exists) | Conventional memory |
0x0009FC00 (typical location) | 0x0009FFFF | 1 KiB | RAM (unusable) | EBDA (Extended BIOS Data Area) |
0x000A0000 | 0x000FFFFF | 384 KiB | various (unusable) | Video memory, ROM Area |
由上表可以发现,目前0-0x4FF,0x9FC00-0xfffff这两段内存是被系统占用了,不能被我们编程使用。
3.外设的使用
BIOS对于外设资源的使用,主要提供了两种方式:其一为中断服务,其二为外设io地址空间。对于外设我们主要关注点为显示器,键盘,串口,硬盘。
对于外设的使用与控制,我觉得一个很有用的观点是来之于《PC内幕技术》——资料的来源:
大多数情况下,我首先回顾了一下制造商为子系统提供的ic数据源清单,然后仔细察看这些芯片在标准主板上是如何具体连接的,做到这一点需要用到系统的原理图,在某些情况下,还要查看系统的电路图。我也仔细研究了不同制造商提供的反汇编BIOS代码,以便在这些较低的层次上考察它们与子系统的联系。我还生成了一些测试程序来检验某西子系统的操作。最后,我才去看那些“正式”的文档,包括IBM的技术参考资料,当然它也是许多其他技术书籍的资料来源。
上面的一段话对如何认识与学习ic子系统提供了基本而且严谨的步骤与方法,很值得我们每个人向前辈学习。也幸好有前辈们的铺垫,我们只需要在已经有的文档中与代码中,理解相关核心而基本的概念,然后使用总结好的代码,保证我们能够对系统有更好的理解与实现。
如下为详细的介绍相关外设的知识:
A)键盘——PS/2 keyboards
作为分析的一个最简单的外设——主要作为输入设备,它的控制芯片为Intel 8042 microcontroller。默认了qemu是模拟的IBM PC/XT Keyboard 的键盘按键,其扫描码详情见:http://www.computer-engineering.org/ps2keyboard/scancodes1.html
系统组织结构图如下,详情可见《PC内幕》8.1图:
键盘的基本工作原理:键盘检测到按键按下,然后将按键扫描码通过串口发送给主板的8042,接着被翻译为系统扫描码,放入输出缓存中,最后通过IRQ9给处理器。
另外,读取键盘按键发送给主板的时序如下:
如上所述,读取按键的方法有两种,一种就是通过中断服务IRQ 9;另一种为通过io指令读取8042缓存的按键值。
如下提供一种通过io指令读取按键的方法——参考8042提供的io口寄存器配置如下表:
Port | Read / | Function |
0x60 | Read | Read Input Buffer |
0x60 | Write | Write Output Buffer |
0x64 | Read | Read Status Register |
0x64 | Write | Send Command |
如下为读取按键的代码示例:
kbRead:
1:
in $0x64,%al#读取通讯状态
andb %al,0x01#检测接收按键扫描码是否ok
jz 1b
in $0x60,%al #读取键值
由以上参考读取按键的流程,在读取键值之前需要读取按键是否准备好,因为由一个通信的过程。
如果想进一步了解,请参考如下的内容:
http://www.computer-engineering.org/ps2keyboard/
http://retired.beyondlogic.org/keyboard/keybrd.htm#1
或者参考《IBM.PC.汇编语言程序设计(第五版)完整版》第10章,《PC内幕技术》第8章。
B)串口——UART
对于串口的理解,我们可以通过两种方式去理解,其一是属于数据通信的范畴,数据通信一般需要考虑的问题:数据(帧)格式(数据位序LSB),数据传输速率,出错控制,流量控制;另外,串口又作为系统的外设,又需要中断控制,一般由如下芯片实现其功能:
芯片编号 | 描述 |
8250 | 基本UART功能支持,最早的串口芯片 |
8250A/B | 比8250更快 |
16450 | 8250的改进,IBM-AT上使用,支持38.4KBPS |
16550 | 在16450基础上,加入接收与发送的FIFO |
16552 | 支持2个16550UART |
16C454/16C1450/16C1550 | 支持4路16550UART,同时支持程序可控的掉电与重起 |
16650/17650 | 支持更多的FIFO |
所以根据如上的描述可以得出串口的属性:
(1)波特率——最小波特率,最大波特率
根据标准的串口的频率表,可以得到最大的波特率如下:
串口频率 | 1.8432Mhz | 2.4546Mhz |
最大波特率 | 115.2 KBPS | 153.6 KBPS |
如果设置其他的波特只需要直接分频即可。
比如:0x03 = 38,400 BPS
(2)数据格式——数据长度,字节序(LSB),终止位,奇偶校验
(3)流控——FIFO的支持——常见的模式没有使用
(4)传输状态——是否传输成功与出错
python学习之前篇---理论知识