为了让计算机显示内容,通常需要两种硬件,显示器和显卡。显卡是为显示器提供内容,并控制显示器的显示模式和状态,显示器的职责是将内容以视觉可见的方式呈现在屏幕上。
通常,显卡是独立生产、销售的部件,需要插在主板上才能工作,这种被称为独立显卡也就是常说的独显。每台计算机都有主板,它就在机箱内部,有时间你可以打开机箱来观察一下。 当然,显卡未必一定是独立的插卡。为了节省使用者的成本,有的显卡会直接做在主板上,这样的显卡也有个名字,叫集成显卡也就是常说的集显。
就和CPU一样,需要从内存里面读取东西再来控制。而显卡也一样,需要从存储器里读取要显示的内容,然后传送给显示器。由以为这个存储器是给显卡用的,所有又叫显示存储器 (Video RAM:VRAM),简称显存。要显示的内容都预先先写到显存里面。
显卡控制显示器的最小单位是像素,一个像素对应着屏幕上的一个点,通过控制每个像素的明暗和 颜色,我们就能形成文字和图像:
显存里面存放了要显示的内容也就是像素的数据,然后显卡周期性地从显存中提取这些比特,并把它们按顺序显示在屏幕上。
像素是显示的最小单元,只要通过像素的多种组合就可以显示我们想要的内容,比如说显示一个QQ头像,和文字内容,但是像素的最基本就是颜色,通过对颜色的处理来控制显示的内容。因为颜色的不同也有不同的显示和存储方式。
只需要把不亮当成比特“0”,亮看成比特“1”。然后将显存里的每个比特和显示器上的每个像素对应起来, 就能实现这个目标。
比如:
这里显存的内容是:10001011然后对应到显示器上就是白黑黑黑白黑白白。就可以通过这种组合来显示内容。
现在的显示器可以显示彩色,彩色的显示器对应的每个像素的每种颜色都是由红绿蓝三元色组成,每种颜色都有256种的深度(深浅/饱和度)。三个不同颜色的颜色就会合成成一个特定的像素:
如图: 左边这个是早期的阴极射线管,右边的是现在比较流行的液晶显示器(LCD Liquid Crystal Display)
也就是说每个像素有 256x265x256 = 16777216种色彩
黑色和白色只需要1 个比特就能表示,但要显示更多的颜色,1 个比特就不够了。现在最流行的,是用24 个比特,即3 个字节,来对应一个像素 。 因 为 2的24次方=16777216 , 所 以 在 这 种 模 式 下 ,同 屏 可 以 显 示 16777216 种颜色,这称为真彩色。也就是我们平常用的。
注:像素是显示器上的最小单位是直接显示的,而对应的比特是显存里面存放的内容。
然后3个字节中,第一个字节对应于红元素,第二个字节对应于绿元素,第三个字节对应于蓝元素,然后每个字节的大小对应于它们的饱和度。
前面我们说过,通过对像素的各种排列组合可以显示出我们想要的内容,比如说显示一个白色的字母'H',就可以很多个白色的像素组合在一起然后显示出来。
所以说不管是显示图片还是文字还是视频,对于显示器来说都没有什么不同,因为它只需要显示像素的就行了。
但是如果我们按照一个像素一个像素的拼起来,这样是非常耗费时间的,而且干的可以说是体力活了,没啥技术含量。
为了方便,工程师设计出了两种CPU的运行模式,文本模式和图像模式这两种CPU的基本工作模式。这两种工作模式的显存是独立分开的。在不同的工作模式下,显卡对显存内容的解释是不同的,根据不同的规则进行对应。
在文本模式下,显存的内容是显示字符所准备的编码。在图像模式下显存的内容是像素的颜色的编码。
就像一个二进制数既可以是一个普通的数,也可以是一条处理器指令一样,每个字符也可以和一个数字进行对应。
比如,数字0x4C 就代表字符“L”,这个数被称为是字 符“L”的ASCII 编码。ASCII编码其实就是一种对应规则,就像一元一次函数一样,每个X对应一个一个y。(当然肯定也有别的编码规则。)
由于历史的原因,所有在个人计算机上使用的显卡,在加电自检中BIOS会执行一个硬件的初始化把自己初始化到80× 25 的文本模式。在这种模式下,屏幕上可以显示25 行,每行80 个字符,每屏总共2000 个字符。然后通过字符发生器读取显存中保存的内容然后将其显示到显示器上。
为了给出要显示的字符,CPU需要访问显存,来把字符的对应的内容写进显存里。但是,显存是位于显卡上的,访问显存需要和显卡这个外围设备打交道。这样效率就会降低了。
所以,计算机系统的设计者们,决定把显存映射到CPU可以直接访问的内存空间。
前面我们说过,8086 可以访问1MB 的内存空间。其中, 0x00000~9FFFF 属于常规内存,由内存条来提供;0xF0000~0xFFFFF 由主板上的一个芯片提供,也就是ROM-BIOS。这样一来,中间还有一个320KB 的空间,也就是0xA0000~0xEFFFF。 传统上,这段地址空间由特定的外围设备来提供,其中就包括显卡。
一直以来,0xB8000~0xBFFFF 这段物理地址空间,是给显卡的,由显卡来提供,用来显示文本的。除非显卡出了毛病,否则这段空间总是可以访问的。
由于显示模式的内容保存在内存的0xB8000~0xBFFFF 这段物理地址空间里的,所以我们就直接往这里写内容就可以了。但是需要遵守对应规则。这里的规则存储对应规则就是:屏幕上的每个字符对应着显存中的两个连续字节,前一个字节是字符的 ASCII 代码,后一个字节是字符的显示属性,包括字符颜色(前景色)和底色 (背景色)。
ASCII:ASCII码一览表,ASCII码对照表 (biancheng.net)
字符颜色:字符的显示属性(1 字节)分为两部分,低4位定义的是前景色,高4位定义的是背景色。色彩主要由R、G、B 决定,毕竟,可以由红(R)、绿(G)、蓝(B)三原色来配出其他所有颜色。K 是闪烁位,为0 时不闪烁,为1 时闪烁;I 是亮度位, 为0时正常亮度,为1 时呈高亮:
KIRGB的所有可能组合:
比如要显示一个白色黑底色的Hello字符串:
将颜色字节解析出来就是: 0x07 = 0000 0111 对面前面的图,0000的背景色为黑色,0111对应的前景色为白色。
显示缓冲区分为8页,每页为4KB(约等于4000B)。通常情况下显示第0页的内容。和显存中的内存对照后,也就是会将B8000H~B8F9H中的4000个字节的内容将显示在显示器上。
然后来一个简单的程序试一下:
data segment db "Maggie" data ends code segment assume cs:code,ds:data start: mov dx,11001000B;显示的字体 mov ax,0b800H mov ds,ax mov ax,data mov es,ax mov bx,0 mov si,0 mov cx,6 loop1: mov ax,es:[bx] mov [bx],ax inc si mov [si],dx inc si inc dx loop loop1 code ends end start
注,这里只是个简单的程序,没有处理成硬盘里面的二进制形式。