1、BIOS(Base Input & Output System)
(1)上电自动加载到内存。占用内存小,8086 占用64KB,只支持一些保证重要和实模式下计算机能运行的基本IO操作。
(2)写在RAM中
(3)BIOS执行流程
由硬件将BIOS映射到0xF0000~0xFFFFF,入口地址为0xFFFF0,CS:IP被强制指向此地址。并执行该地址下的代码远跳转(jmp far 0xF000:0xE05B)。0xFE05B存放BIOS真正的执行代码。
检测外设,设置中断向量表。
然后BIOS执行程序从硬盘第一个扇区加载MBR到内存0x7C00位置,并jmp 0: Ox7c00。BIOS执行程序在0盘0道1扇区(CHS),扫描扇区最后2字节是不是魔术0x55和0xaa(小端0xaa55)来确定是不是MBR。然后把MBR程序加载到内存0x7c00。
2、BIOS中断int 0x10,封装了屏幕显示的功能。但是一般不用这个中断,而是往内存显示区域写入数据,显卡再往该内存读取。int 0x10原理也是一样。
3、Intel 8086有20条地址总线,故可以访问内存范围0x00000~0xFFFFF。超过0xFFFFF部分,直接不要,既是回卷溢出。
4、DRAM、L1、L2、L3级缓存区别
(1)DRAM(Dynamic Random Access Memory),之所以称为动态是因为内存中电容漏电快,需要及时补电刷新。
(2)相反还有SRAM,例如L1、L2级缓存,不需要刷新。L1和L2在容量,远近,制程上,导致访问速度L1>L2。
(3)由于L3 Cache的时延要求没有那么高,现在大家也要考虑不使用SRAM,转而使用STT-MRAM,或是eDRAM来做L3 Cache。
5、地址总线并不会全部用于访问DRAM,需要预留一些访问外设。如:IO口地址控制接口地址译码器使能那个外设使用数据总线
6、CPU通过地址总线将要操作的地址传输写内存,内存再通过数据总线向CPU传输机器码。
7、CHS扇区编号从1开始,LBA扇区编号从0开始。
8、nasm会将相同类型的段划分一起,伪代码section只起标记段类型作用,vstart定义段起始地址。
9、$$
:段的起始地址,$
:以段为地址基准顺延,当前位置的地址。$-$$
:当前位置地址-段起始地址=段为基准的地址偏移
10、nasm常用命令:nasm -f >file name> [- o utput> ]
11、dd if=/your_path/mbr.bin of=/your_path/bochs/hd60M.img bs=512 count=1 conv=notrunc
bs,块大小。
count,写入几个块,上面的命令表示写入1个块大小为512字节数据块。
conv=notrunc,不清除所有hd60M.img,只是从指定位置开始覆盖。例如上面命令只写入第一个扇区512字节,那么512字节后的内容不会被清除。
seek,为跳过第几块开始写入,默认0。
12、bochs 启动命令:bochs -qf bochsrc
13、代码
mbr.asm
;代码以此地址作为偏移地址的基地址
[ORG 0x7c00]
;指定代码段和16bit模式
[SECTION .text]
[BITS 16]
_start:
mov ax, cs ;段寄存器清0
mov ds, ax
mov es, ax
mov ss, ax
mov fs, ax
mov sp, 0x7c00 ;设置栈寄存器sp,栈地址从上往下存储,恰好0x500~0x7bff是可用区域
;int 0x10 相当函数,参数从ax,bx,cx,dx这些寄存器取。清掉BIOS的输出。
mov ax, 0x0600 ;ah=0x06,表示功能号,功能为上卷清屏.al=0x0,表示上卷行数,为0则表示全部
s line,the zero is all.
mov bx, 0x0700 ;上卷属性,黑底
mov cx, 0 ;左上角坐标(0, 0)
mov dx, 0x184f ;右下角坐标(24, 79), 0x18=24,0x4f=79
int 0x10 ;0x10中断
;打印字符
mov ax, message ;将message内存地址传给ax
; (0) [0x00007c21] 0000:7c21 (unk. ctxt): mov ax, 0x7c33 ; b8337c 这里0x7c33既是message地址,编译器编译时自动转换。所以message只是方便编程>的符号。
mov bp, ax ;由于bp不能直接传址,但可以通过通用寄存器传址。es:bp指向字符串首地址
mov dx, 0 ;设置起始显示光标(0, 0)
mov cx, 3 ;字符串长度
mov ax, 0x1301 ;ah=0x13,功能号,显示字符串。al=0x01,设置写字符方式,为显示字符,光标跟随移动。显示字符功能号还有09、0a、0e。oe可以结合循环,判断字符串是否到si寄存器指>向0。
mov bx, 0x2 ;bh=0x0,要显示的页号,这里只用第1页。bl=0x2字符属性,黑底绿字
int 0x10
jmp $ ;在这行的地址处循环跳转,相当于while(1)
message db "MBR",13,10,'$' ;message会在编译时转换为当前行地址,并作为字符串首地址
;<bochs:10> xp /10bc 0x7c33
;0x00007c33 <bogus+ 0>: M B R
times 510-($-$$) db 0 ;一个扇区512字节,减去0xaa55为510字节。($-$$)为上面代码所占用字节数,510-($-$$)为当前行到魔术符字节数。time 字节数 dd 0 : 填充当前字节开始,
到字节数为0
dw 0xaa55 ;BIOS程序识别MBR魔术符
14、Makefile
.PHONY:build image clean
obj=mbr.bin
build:
nasm mbr.asm -o $(obj)
image:
dd if=./mbr.bin of=./hd60M.img bs=512 count=1 conv=notrunc
clean:
rm -rf *.img $(obj)
15、运行
(1)code tree
root@intel-S2600IP:~/systemcode/Pinux# tree
.
├── bochsrc
├── Makefile
├── mbr.asm
(2)在bochsrc 文件目录下运行下面命令
root@xian-S2600IP:~/systemcode/Pinux# bochs -qf bochsrc
(3)结果
本文以学习交流为目的,有错处请多指教。