端口的概念
各种存储器都要和CPU的地址线,数据线,控制线相连,在CPU看来,总线就是一个由若干个存储单元构成的逻辑存储器,称之为内存地址空间。除了各种存储器,通过总线和CPU相连的还有下面三种芯片:
- 各种接口卡(如网卡显卡)上的接口芯片,他们控制接口卡工作
- 主板上的接口芯片,CPU通过它们访问外部设备
- 其他芯片,用来存储相关系统信息,或进行相应的输入输出
上面的芯片中都有一种由CPU读写的寄存器,它们都和CPU的总线相连(通过各自的芯片),CPU对他们进行读写时候都通过控制线向他们所在的芯片发出端口读写指令。
所以,对于CPU来说,将这些寄存器都当做端口,对他们进行统一编址,建立了一个端口地址空间,每一个端口拥有一个地址,所以CPU可以直接读取下面三个地方的数据:
- CPU内部的寄存器
- 内存单元
- 端口
端口的写
因为端口所在的芯片和CPU通过总线相连,所以端口地址和内存地址一样通过地址总线传送,并且在PC系统中,CPU最多可以定位64KB个不同的端口,所以端口地址范围是0~65535。
对端口的读写不能使用mov,push,pop等内存读写指令,端口的读写指令只有两个:in
和out
分别用于从端口读取数据和往端口写入数据。
访问端口的步骤:
例:in al, 60h
; 从60h号端口读入一个字节
- CPU通过地址总线降低至信息60h发出
- CPU通过控制线发出端口读命令,选中端口所在芯片,并通知它要从中读取数据
- 端口所在芯片将目标端口中的数据通过数据线送入CPU
注:在in和out指令中,只能通过ax或al来存放从端口中读入的数据或要发送到端口中的数据,且访问8位端口时,用al,访问16位端口用ax。
对0~255以内的端口进行读写时:
in al,20h
out 20h,al
对256~65535的端口进行读写时,需要将端口号写在dx中:
mov dx,3f8h
in al,dx
out dx,al
CMOS RAM芯片
PC中有一个叫做CMOS RAM的芯片,称为CMOS,有如下特征:
- 包含一个实时钟和一个有128个存储单元的RAM存储器(早期的计算机64个字节)
- 靠电池供电,关机后内部的实时钟仍可继续工作,RAM中的信息不丢失
- 128个字节的RAM中,内部实时钟占用0~0dh单元保存时间信息,其余大部分单元用于保存系统配置信息,供系统启动时BIOS程序读取,BIOS也提供了相关的程序可以让我们在开机时配置CMOS中的系统信息。
- 芯片内部有两个端口70h和71h,CPU通过这两个端口读写CMOS
- 70h为地址端口,存放要访问CMOS单元的地址,71h为数据端口,存放从选定的单元中读取的数据,或写入的数据。
所以可以看出,想要从CMOS中读取数据,应分两步,先将单元号送入70h,然后再从71h读出对应号的数据。
shl和shr指令
shl和shr是逻辑移位指令,shl是逻辑左移,功能为:
- 将一个寄存器或内存单元中的数向左移位
- 将最后移出的一位写入CF
- 最低位补0
如: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*2。
右移shr同理,最高位用0补充,移出的写入CF,若移动位数大于1,也要写在cl中,相当于x=x/2
在CMOS中存放着当前时间的年月日时分秒,分别存在下面的单元内:
秒 | 分 | 时 | 日 | 月 | 年 |
---|---|---|---|---|---|
0 | 2 | 4 | 7 | 8 | 9 |
每个信息使用一个字节存放,以BCD码的形式,BCD码是对0-9这几个数字使用二进制表示,如:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 |
如果要表示一个两位数如13,就是一个字节高四位是十位1的BCD码,低四位是个位3的BCD码,表示为00010011b。下面程序获取当前月份:
···
mov al,8
out 70h,al ;要从8号单元读取数据,所以先将8号单元送入70h端口
in al,71h ;从71h端口拿数据
mov ah,al ;复制一下
mov cl,4
shr ah,cl ;ah右移四位,ah里面的就是月份的十位
and al,00001111b ;al里面剩下的就是月份的个位