控制显卡

1 显卡和显存

1.1 显卡和显存

先搞清楚如下几个概念:
显卡: 为显示器提供内容。
显示器: 将显卡所提供的内容呈现在屏幕上。

集成显卡: 集成在主板上,和主板是一体的。
独立显卡: 独立生产和销售的一个独立的部件。

显示存储器: 简称“显存”,每个显卡都有自己的存储器。

1.2 显存的显示模式

图形模式:
在这里插入图片描述
文本模式:
在这里插入图片描述
实际上还包含属性字节:
在这里插入图片描述
属性字节的含义:
在这里插入图片描述

1.3 8086中显存的地址

在这里插入图片描述


2 控制显卡显示内容

2.1 需求分析

我们需要在屏幕上显示一个标号的地址,显示内容类似:“label offset:256”。

显示标号的步骤如下:
在这里插入图片描述

2.2 汇编代码实现

汇编代码如下:

mov ax,0xb800   
;将b800传送到ax寄存器中             
mov es,ax
;将ax寄存器中的值,也就是b800传送到附加段寄存器es中
;为什么不写成  mov es,b800 ?
;因为intel处理器不允许,它只允许:mov 段寄存器,通用寄存器/内存单元
;b800这个数是干什么用的?---显存的段地址							
;----------------------------------------------------------------- 
mov byte [es:0x00],'L'
;"字符L的ASCII码"存储到显存的第1个存储单元中
;mov byte [es:0x00],0100 1100b / 76 / 0x4C
;地址必须使用方括号括起来 
;byte/word:明确的告诉编译器这条指令的数据宽度 
;不需要修饰:Mov  [00],AL  /  Mov  AX,[00]
mov byte [es:0x01],0x07
;"字符L的属性"存储到显存的第2个存储单元中
;属性值07:黑底白字、无闪烁、无加亮

mov byte [es:0x02],'a'
mov byte [es:0x03],0x07

mov byte [es:0x04],'b'
mov byte [es:0x05],0x07

mov byte [es:0x06],'e'
mov byte [es:0x07],0x07

mov byte [es:0x08],'l'
mov byte [es:0x09],0x07

mov byte [es:0x0a],' '
mov byte [es:0x0b],0x07

mov byte [es:0x0c],"o"
mov byte [es:0x0d],0x07

mov byte [es:0x0e],'f'
mov byte [es:0x0f],0x07

mov byte [es:0x10],'f'
mov byte [es:0x11],0x07

mov byte [es:0x12],'s'
mov byte [es:0x13],0x07

mov byte [es:0x14],'e'
mov byte [es:0x15],0x07

mov byte [es:0x16],'t'
mov byte [es:0x17],0x07

mov byte [es:0x18],':'
mov byte [es:0x19],0x07
;-----------------------------------------------------------------
mov ax,number
;"标号"存储到ax寄存器中,作为下面除法运算的:被除数的低16位 
;编译器在编译的时候会将number替换为其所对应的的汇编地址 
mov dx,0
;将0存储到dx寄存器中,作为下面除法运算的:被除数的高16位                
mov bx,10
;将10,也就是二进制的1010存储到bx寄存器中,作为下面除法运算的:除数 
;以上三条指令为第2个步骤的除法运算做好了准备工作 
;----------------------------------------------------------------- 
mov cx,cs 
;将代码段寄存器cs中的值,也就是0x000,传送到cx寄存器中
mov ds,cx  
;将cx寄存器中的值,也就是0x000传送到数据段寄存器ds中
;ds寄存器中存储的是本程序在内存中的段地址
;----------------------------------------------------------------- 
div bx
;对应第1次除法运算
;商存储在ax寄存器中,作为下次运算的被除数 
;余数,也就是标号的个位上的值存储在dx寄存器中
mov [0x7c00+number+0x00],dl
;将第1次除法运算所得到的标号个位上的值
;存入了我们使用db所声明的第1个存储单元中  
   
xor dx,dx
;异或指令:对两个数进行异或运算,并将结果存储到目的操作数中
;异或运算的特点:相同为0,不同为1
;这条指令的作用:将dx寄存器中的值清零
;为第2次除法运算做准备 
div bx
;对应第2次除法运算
mov [0x7c00+number+0x01],dl  
;将第2次除法运算所得到的标号十位上的值
;存入了我们使用db所声明的第2个存储单元中

xor dx,dx
;为第3次除法运算做准备
div bx
;对应第3次除法运算
mov [0x7c00+number+0x02],dl 
;将第3次除法运算所得到的标号百位上的值
;存入了我们使用db所声明的第3个存储单元中 
;-----------------------------------------------------------------
mov al,[0x7c00+number+0x02]
;将标号百位上的数值传送给al寄存器 
add al,0x30
;获得标号百位上数值的ASCII码
mov [es:0x1a],al 
;将标号百位上数值的ASCII码存入显存            
mov byte [es:0x1b],0x04
;将0x04存入显存中偏移地址为0x1b的存储单元		
;字符属性04:黑底、红字、无闪烁、无加亮

mov al,[0x7c00+number+0x01]
;将标号十位上的数值传送给al寄存器
add al,0x30
;获得标号十位上数值的ASCII码
mov [es:0x1c],al
;将标号十位上数值的ASCII码存入显存
mov byte [es:0x1d],0x04

mov al,[0x7c00+number+0x00]
;将标号个位上的数值传送给al寄存器
add al,0x30
;获得标号个位上数值的ASCII码
mov [es:0x1e],al
;将标号个位上数值的ASCII码存入显存
mov byte [es:0x1f],0x04

mov byte [es:0x20],'D'
;将字符D的ASCII码存入显存 
mov byte [es:0x21],0x07
;字符属性07:黑底白字、无闪烁、无加亮
;-----------------------------------------------------------------  
infi jmp near infi  
;无限循环               
;-----------------------------------------------------------------
number db 0,0,0,0,0
;标号:number = 汇编地址 = 0x0100
;书写规范:以字母开头 
;db:声明并初始化数据
;声明数据的本质就是:在内存中占用一块空间 
;初始化数据的本质就是:给这个空间赋予一个值 
;在内存中占用了5个字节的空间,这5个字节的值都是0 
;-----------------------------------------------------------------
times 249 db 0
;让编译器重复生成db 0 ---- 249次 
db 0x55,0xaa
;硬盘主引导扇区的有效标志 

2.3 更精简的代码实现

        jmp near start
        ;跳过下面的数据区   
  mytext db 'L',0x07,'a',0x07,'b',0x07,'e',0x07,'l',0x07,' ',0x07,'o',0x07,\
            'f',0x07,'f',0x07,'s',0x07,'e',0x07,'t',0x07,':',0x07
  number db 0,0,0,0,0
        ;--------------------------------------------------------------------                
  start: 
         mov ax,0x07c0                  
         mov ds,ax
         
         mov ax,0xb800                 
         mov es,ax
         ;--------------------------------------------------------------------
         cld
         ;作用:将方向标志位清0 :正向 
         ;std指令:将方向标志位置1:反向													 
         mov si,mytext
         ;所要传送的数据,它的偏移地址  						              
         mov di,0    		
         ;所要传送的位置,它的偏移地址							
         mov cx,(number-mytext)/2 
         ;所要传送的次数     
         rep movsw 									
         ;--------------------------------------------------------------------
         mov ax,number
         ;AX:被除数的低16;目的:让它参与运算,以得到标号各个数位上的值 
         mov bx,ax
         ;目的,将来存储计算所得到的标号各个数位上的值
         mov cx,5 
         ;运算的次数                     
         mov si,10  
         ;除数  
         ;--------------------------------------------------------------------              
  digit: 
         xor dx,dx
         div si
         mov [bx],dl
         ;[bx]:指向了第2条DB指令所声明的第1个存储单元                 
         inc bx
         ;将bx寄存器中的值+1 
         ;目的:下一个循环中,让[bx]指向第2条DB指令所声明的第2个存储单元 
         ;Dec:将bx寄存器中的值-1											
         loop digit
         ;循环 
         ;--------------------------------------------------------------------
         mov bx,number
         ;bx:基址寄存器 							
         mov si,4       
         ;SI:源变址寄存器               
   show:
         mov al,[bx+si]
         ;1次循环,将标号万位上的值存储到了al寄存器中
	 ;2次循环,将标号千位上的值存储到了al寄存器中
         add al,0x30				
         ;获取标号各个数位值的ASCII码				 
         mov ah,0x04	
         ;0x04:字符属性								 
         mov [es:di],ax	
         ;将标号的ASCII码及其属性存入显存中
         ;1次循环-->万位   第2次循环-->千位							
         add di,2
         ;为我们后面的循环,存储标号数位上值的ASCII码及其属性做准备	 			    
         dec si
         ;为我们后面的循环,访问标号各个数位的值做准备						 
         jns show							 
         ;jns:条件转移指令  SF=0跳转  SF=1不跳转 
         ;--------------------------------------------------------------------
         mov word [es:di],0x0744
         ;高字节07:字符属性   低字节44:字符D的ASCII码	
         jmp near $   
         ; == $ jmp near $
         ;执行效果 == infi jmp near infi 
         ;$:当做标号来用 
         times 510-($-$$) db 0 
         ; == $ times 510-($-$$) db 0  
         ;$ = 当前指令的汇编地址
         ;$$ = 当前段($$所在的段)的起始汇编地址 
         ;510-($-$$) = 为保证0x550xaa的位置,所需要添加的字节数     
         db 0x55,0xaa
         
         
    

参考资料:

  1. 深度学习:C/C++、计算机体系
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值