目录
3.3 让我们直接对显示器说点什么吧
3.3.1 CPU 如何与外设通信 —— IO 接口
CPU 系统总线上传送的都是并行数据(所以你听到的都是 8 位, 16 位, 32 位 CPU …)
任何不兼容的问题,都可以通过增加 一 “层” 来解决。(这一“层”就是用来转换的)
在 CPU 和外设之间的这一层就是 IO 接口。IO 接口形式不限,它可以是个电路板、也可以是块芯片、甚至可以是个插槽。半导体、集成电路、电路板、芯片有什么区别?
IO 接口是连接 CPU 与外部设备的逻辑控制部件,既然称为逻辑,就说明可分为硬件和软件两部分,软件是指用来控制接口电路工作的驱动程序以及完成内部数据传输所需要的程序。IO 接口芯片又可按照是否可编程来分类,可分为可编程接口芯片和不可编程接口芯片。
计算机与 IO 接口的通信是通过计算机指令实现的,这种通过软件指令选择 IO 接口上的功能、工作模式的做法,称为 “IO 接口控制编程”。
同一时刻, CPU 只能和一个 IO 接口通信。输入输出控制中心 (I/O control hub, ICH ),也就是南桥芯片:仲裁 IO 接口的竞争,连接各种内部总线。
IO 接口中的寄存器就称为端口,端口是 IO 接口开放给 CPU 的接口。
3.3.2 显卡概述
某些 IO 接口也叫适配器,适配器是驱动某一外部设备的功能模块。显卡也称为显示适配器,不过归根结底它就是 IO 接口,专门用来连接 CPU 和显示器。
显卡的CPU称为GPU,显卡是 pci 设备,所以是安装在主板上 pci 插槽上的,pci 总线是共享井行架构,但对于要保证同时接收n位数据,这是有困难的,于是有了PCI Express 总线,这就是串行设备,简称 pcie,现在的显卡都是串口的了。
3.3.3 显存,显卡,显示器
显存是由显卡提供的,它是位于显卡内部的一块内存,所以它称为显存。显卡的工作就是不断地读取这块内存,随后将其内容发送到显示器(GPU)。
屏幕是由密密麻麻的像素组成的,显存中的每一位都对应屏幕上的一个像素点。
美国信息互换标准代码(American Standard Code for Information Interchange,ASCII):一个字符对应一字节的编码,只要往显存中写入这个编码,显卡就知道这是要打印此字符,由它帮你完成像素的拼凑。ASCII 是一套“字符”标准,它只会打印出字符,数字0可不是在屏幕上输出的0,屏幕上的0那可是字符‘0’,所以想输出0,得输出数字 0x30。
显卡支持三种模式,文本模式,黑白图形模式,彩色图形模式。显卡的文本模式也是分为多种模式的,用“列数*行数”来表示,它们的乘积是整个屏幕上可以容纳的字符数。显卡在加电后,默认就置为模式 80*25。每个字符在屏幕上都是由 2 个字节来表示的,而且是连续的 2 个字节,低宇节是字符的 ASCII 码,高字节是字符属性元信息。
3.3.4 改进 MBR,直接操作显卡
相关命令:
nasm -o mbr.bin mbr.S 编译文件
dd if=mbr.bin of=hd60.img bs=512 count=1 conv=notrunc 写入磁盘文件
bin/bochs -f bochsrc.disk 执行启动
;主引导程序 MBR
;————————————————————————————————————————————————————————————
SECTION MBR vstart=0x7c00
mov ax,cs ;此时cs中的值为0x0
mov ds,ax ;用cs寄存器的值来初始化其他寄存器的值,
mov es,ax ;因为没有从立即数到段寄存器的电路实现,只有通过其他寄存器来中转
mov ss,ax
mov fs,ax
mov sp,0x7c00 ;初始化栈指针,栈是向下发展的,是程序就要用到栈???
mov ax,0xb800 ;显存文本模式中,其内存地址是 0xb8000
mov gs,ax
;————————————————————————————————————————————————————————————
;清屏,因为在 BIOS 工作中,会有一些输出,如检测硬件的结果信息等。为了让大家看清楚我们在MBR 中的输出字符串,故先把 BIOS 的输出清掉,这里演示的是 BIOS 中断 int 0x10 的用法。
;清屏利用 0x06 号功能,上卷全部行,则可清屏
;INT 0x10 功能号:0x06 功能描述:上卷窗口
;输入:
;AH 功能号= 0x06
;AL =上卷的行数(如果为0,表示全部)
;BH =上卷行属性
;(CL, CH) =窗口左上角的(X,Y)位置
;(DL, DH) =窗口右下角的(X,Y)位置
;无返回值
mov ax,0x600
mov bx,0x700
mov cx,0 ;左上角(0,0)
mov dx,0x184f ;右下角(80,25)
;VGA 文本模式中,一行只能容纳 80 个字符,共 25 行
;下标从0开始,所以 0x18=24,0x4f=79(好像是 列,行 坐标?)
int 0x10
;————————————————————————————————————————————————————————————
;输出背景色绿色,前景色红色 ,并旦跳动的字符串“hello!”
mov byte [gs:0x00], ‘H’ ;对于立即数是无法判断它的存储空间的,所以要关键字指定
mov byte [gs:0x01], 0xA4 ;A表示绿色背景闪烁, 4表示前景色为红色
mov byte [gs:0x02], ‘e’
mov byte [gs:0x03], 0xA4
mov byte [gs:0x04], ‘l’ ;对于立即数是无法判断它的存储空间的,所以要关键字指定
mov byte [gs:0x05], 0xA4 ;A表示绿色背景闪烁, 4表示前景色为红色
mov byte [gs:0x06], ‘l’ ;对于立即数是无法判断它的存储空间的,所以要关键字指定
mov byte [gs:0x07], 0xA4 ;A表示绿色背景闪烁, 4表示前景色为红色
mov byte [gs:0x08], ‘o’ ;对于立即数是无法判断它的存储空间的,所以要关键字指定
mov byte [gs:0x09], 0xA4 ;A表示绿色背景闪烁, 4表示前景色为红色
mov byte [gs:0x0A], ‘!’ ;对于立即数是无法判断它的存储空间的,所以要关键字指定
mov byte [gs:0x0B], 0xA4 ;A表示绿色背景闪烁, 4表示前景色为红色
;————————————————————————————————————————————————————————————
jmp $ ;使程序悬停在此
times 510-($-$$) db 0
db 0x55,0xaa