第十四章
CPU在操控各种存储器时,都把它们当作内存来对待,把它们总地看做一个由若干存储单元组成的逻辑存储器,这个逻辑存储器我们称为内存地址空间
PC机中,除了各种存储器外,还有以下3种芯片和CPU通过总线相连
1、各种接口卡(网卡、显卡)上的接口芯片,它们控制接口卡进行工作
2、主板上的接口芯片,CPU通过它们对部分外设进行访问
3、其他芯片,用来存储相关的系统信息,或进行相关的输入输出处理
这些芯片中都有一组可以由CPU读写的寄存器,它们在物理上处于不同芯片上,但有两个共同点
1、都和CPU的总线相连(通过它们所在的芯片进行)
2、CPU对它们进行读或写的时候通过控制线向它们所在的芯片发出端口读写命令
从CPU角度,将这些寄存器都当作端口,对它们进行统一编址,建立一个统一的端口地址空间,每一个端口在地址空间中都有一个地址
至此,CPU可以直接读写以下3个地方的数据
1、CPU内部的寄存器
2、内存单元
3、端口
14.1 端口的读写
CPU通过端口地址定位端口进行访问,,因为端口所在的芯片和CPU通过总线相连,所以,端口地址和内存地址一样,通过地址总线来传送,CPU最多可以定位64KB个不同的端口,端口地址为0~65535
端口的读写指令只有两条:in和out,分别从端口读取/写入数据
比较CPU执行内存访问指令和端口访问指令时候,总线上的信息
访问内存:moc ax,ds:[8]
执行时总线相关的操作如下
1、CPU通过地址线将地址信息8发出
2、CPU通过控制线发出内存读命令,选中存储芯片,并通知它将要从中读取数据
3、存储器将8号单元中的数据通过数据线送入CPU
访问端口:in al,60h ; 从60端口所在芯片读入一个字节
执行时总线相关的操作如下
1、CPU通过地址线将地址信息60h发出
2、CPU通过控制线发出端口读命令,选中端口所在芯片,并通知它将要从中读取数据
3、端口所在芯片将60h端口中的数据通过数据线送入CPU
注意,in和out指令中,只能使用ax或al来存放从端口中读入的数据或要发送到端口中的数据,访问8位端口时用al,访问16位端口时用ax
; 对0~255以内的端口进行读写时
in al,20h ; 从20h端口读入一个字节
out 20h,al ; 往20h端口写入一个字节
; 对256~65535以内的端口进行读写时,端口号放在dx中
mov dx,3f8h
in al,dx ; 从3f8h端口读入一个字节
out dx,al
14.2 CMOS RAM芯片
PC机中有一个CMOS RAM芯片,简称CMOS,其有如下特征
1、包含一个实时钟和128个存储单元的RAM存储器
2、该芯片靠电池供电,关机后内部的实时钟仍可正常工作,RAM中的信息页不会丢失
3、128个字节中,内部时钟占0~0dh单元来保存时间,其余大部分单元保存系统配置信息,供启动时BIOS程序读取,BIOS也提供相关程序使得在开机时能够配置CMOS中的系统信息
4、芯片内部有两个端口,地址为70h和71h,CPU通过这两个端口进行读写CMOS RAM
5、70h为地址端口,存放要访问的CMOS RAM单元的地址,71h为数据端口,存放从选定的CMOS RAM单元读取或要写入其中的数据
总结,CPU对CMOS RAM的读写分为两步进行,如读CMOS RAM的2号单元
将2送入端口70h,从71h读出2号单元的内容
mov al,2
out 70h,al
in al,71h
14.3 shl和shr指令
shl和shr是逻辑位移指令
shl是逻辑左移指令
功能:将一个寄存器或内存单元中的数据向左移位,将最后移出的一位写入CF,最低位补零
mov al,01001000b
shl al,1 ; 左移一位 (al)=10010000b CF=0
如果移动位数大于1,移动位数放在cl中
mov al,01010001b
mov cl,3
shl al,cl ; (al)=10001000b 最后移出的一位是0,所以CF=0
将X逻辑左移一位,相当于X=X*2(会有溢出)
shr是逻辑右移
功能:将一个寄存器或内存单元中的数据向右移位,将最后移出的一位写入CF,最高位补零
如果移动位数大于1,移动位数放在cl中
将X逻辑左移一位,相当于X=X/2(会有溢出)
编程,用加法和移位指令计算(ax)=(ax)*10
mov bx,ax
shl ax,1
mov cl,3
shl bx,cl
add ax,bx ;(ax)=(ax)*2+(ax)*8
14.4 CMOS RAM中存储的时间信息
CMOS RAM中,存放着当前的时间:年、月、日、时、分、秒,它们的长度都为一个字节
存放单元:秒:0
分:2
时:4
日:7
月:8
年:9
这些数据以BCD码的方式存放
BCD码是以4位二进制数表示十进制数的编码方法
如26用BCD码表示:0010 0110
可见一个字节可表示两个BCD码,在CMOS RAM存储时间信息的单元中,存储了用两个BCD码表示的两位十进制数,高4位的BCD码表示十位,低4位表示个位
如 00010100b表示14
编程,在屏幕中间显示当前的月份
assume cs:code
code segment
start: mov al,8
out 70h,al ; 存储在CMOS RAM的8号单元
in al,71h ; 从数据端口取得指定单元中的数据
mov ah,al
mov cl,4
shr ah,cl ; ah中为十位的数码值(8位的高4位为0)
and al,00001111b ; al中为个位的数码值(8位的高4位为0)
add ah,30h ; BCD码+30h=十进制数对应的ASCII码
add al,30h
; CMOS中一个字节可以表示一个月份,但由于可能存在两位数
; 所以个位十位分别存在两个寄存器中
; 这样方便转换为ASCII码,作为字符进行显示12 = '1' '2'
mov bx,0b800h
mov es,bx
mov byte ptr es:[160*12+40*2],ah ; 十位
mov byte ptr es:[160*12+40*2+2],al
mov ax,4c00h
int 21h
code ends
end start
实验十四
编程,以年/月/日 时:分:秒 的格式,显示当前的日期、时间
assume cs:code,ds:data
data segment
db 'yy/mm/dd hh:mm:ss'
db 9,8,7,4,2,0
data ends
code segment
start: mov ax,data
mov ds,ax
mov si,0
mov di,17 ; CMOS中偏移地址的索引
mov cx,6
s: push cx
mov al,[di]
out 70h,al
in al,71h ; 从71h端口获取数据
mov ah,al
mov cl,4
shr ah,cl ; ah保存十位上的数字
and al,00001111b ; al保存个位上的数字
add al,30h ; 得到对应字符的ASCII码
add ah,30h
mov [si],ah ; 保存到data段中
mov [si+1],al
add si,3 ; 指向下一个要填入数据的地址
add di,1
pop cx
loop s
mov ax,data
mov ds,ax
mov si,0
mov cx,17
mov ax,0b800h
mov es,ax
mov di,160*13+32*2
s1: mov al,[si]
mov es:[di],al
mov al,02h ; 颜色属性
mov es:[di+1],al
inc si
add di,2
loop s1
mov ax,4c00h
int 21h
code ends
end start