既然都说到IO接口了,不知道各位有没有疑问,cpu是怎样访问到IO接口呢?肯定得有个链路吧?什么?有隐约听到有同学开玩笑说:cpu用无线访问其它设备。哈哈,不知道各位听说过没有,无线的终端是有线。无论无线设备再如何强大,最终在网络的那一头,必然是物理设备在支撑。所以,不如用个物理链路啦,你看主板上密密麻麻的线路就知道为什么有些人称主板为线路板啦。其实这物理链路就是一组电线,这条电线用于传送信号,故称为信号线。那些想和其它硬件交流的设备就要想办法连接到这条线上。由于这条电线是供大家使用的公共线路,属于所有设备共享,所以形象的称之为bus,公共汽车。也就是大家所说的总线,总之,总线并不是抽象出来的东西,它就是把大家连接到一起的电线。再形象一点说,总线就像一条高速公路,这公路上有很多出口可以让汽车进出,汽车在计算机中就相当于各种硬件设备,可以选择连接上总线,也可以选择从总线分离。
同一时刻,cpu只能和一个IO接口通讯,当很多的IO接口同时想和cpu对话时,面对众多接口的爱慕,cpu会选择和谁单独一叙呢?这个工作不应该由cpu来做,前面说过啦,cpu太忙了,还是好钢使在刀刃上吧,既然分层能解决问题,咱们再加一层,这一层的责任是除了仲裁IO接口的竞争,还要连接各种内部总线。由于它的使命,它的名字就叫做输入输出控制中心ICH(I/O control hub),也就是南桥芯片。如图
说到了南桥,多少还要提一句北桥芯片的作用。图上标上北桥部分其实是散热片,在它下面才是北桥。由于南桥和北桥一般是成对出现的,至少在支持intel cpu的主板中是这样的(话说,AMD为了减少cpu同北桥交换数据的成本,已经把北桥的工作放到了cpu内部,所以支持AMD的板子上未必有北桥芯片)。南桥是用于连接pci、pci-express、AGP等低速设备,北桥是用于连接高速设备,如内存。
好啦说完啦,点到为止,还得要继续说南桥。cpu通过内部总线连接到南桥芯片中的内部,这个内部总线是专用的,它只通向位于南桥中的cpu接口。说的好炫,其实还是一条电线而已。从名字上可以看出,南桥二字中的桥,其实对应的是hub这个单词,它们都意为“公共、集合”,所以不难想像,在南桥内部集成了一些IO接口,如并口硬盘PATA(就是我们平时所说的IDE硬盘),串口硬盘SATA,USB、PCI设备,电源管理等接口。由于这些接口对微型计算机来说必不可少,它们就直接扎根在南桥内部啦。
在南桥内部的接口对微型计算机来说是不可少的,除了这些之外,那些可有可用的设备,难道南桥就不管了吗?必须得管,这毕竟是它的工作。南桥芯片内部总线示意如图:
为了支持这些非必要的设备(当然主要是为了方便扩展,不易扩展的产品意味着从出生那天就开始走向灭亡),南桥提供了专门用于扩展的接口,这就是PCI接口。在主板上有很多插槽,它们就是预留的pci接口,pci设备可以即插即用。由于它们延伸到了南桥外面,又像公路一样,很多pci设备都可以连接上来,所以这条延长的PCI接口便成了PCI总线。结合图3-11和图3-12。看到主板上那些并排的插槽时,大家要想到,它们其实都“骑”在一条电线上,这样理解总线容易些吗?
看到一个总线又一个总线的,如果感觉烦乱的话,说明总线这个词意义不明确,也许翻译成“公共线路”最直接。简单的东西通过术语搞得好深奥,完全一副不明觉厉的样子。其实大家想想看,这么多设备要实现相互通讯,不得用电线连接到一起吗?只不过大多数情况下,连接到这条电线上的设备不止两个,总的数量较多,所以称之为“总”线。由于用途不同,这些电线有了各种各样的名字,如地址总线、数据总线、ISA总线等等。总之,不要被总线这个词吓到,它其实就是电线。
以上都是接口的硬件部分,咱们最终是要通过软件方式使用这些硬件,下面看看咱们为了驱动这些硬件要做什么。
IO接口在诞生之初,就被设计成要通过寄存器的方式同cpu通讯,其内部有专用于数据交互的寄存器,只不过这里所说的这些寄存器是位于IO接口中,为了区别于cpu内部的寄存器,IO接口中的寄存器就称为端口(这可不是网络应用程序所开的那种端口,如网络服务器会启动80端口,这是两码事)。
IO接口是连接cpu和硬件的桥梁,一端是cpu,另一端是硬件。端口是IO接口开放给cpu的接口,一般的IO接口都有一组端口,每个端口都有自己的用途,甚至有时,一个端口在不同情况下有不同的用途。可见IO接口另一端的硬件,相对来说还是很复杂的,所以,当看到某个IO接口上那么多端口的介绍而烦乱时,停止抱怨,IO接口已经为咱们极大的简化了操作。
端口也是寄存器,寄存器就有数据宽度,有8位、16、32位,各个设备是不一样的,看厂商自己安排了。
如何访问到端口呢,外设中的rom既然可以通过内存映射来访问,端口也可以,确实有些微机系统中是这样做的,把一些内存地址做为端口的映射,访问这些内存地址就相当于访问了这些端口。还有一些微机系统把端口独立编址,把所有端口从0开始编号,位于一个IO接口上的所有端口号都是连续的。以后讲解硬盘的时候大家就会看到了。
IA32体系系统中,因为用于存储端口号的寄存器是16位的,所以最大有65536个端口,即0~65535。
要是通过内存映射,端口就可以用mov指令来操作。但由于用的是独立编址,所以就不能把它当作内存来操作,因些cpu提供了专门的指令来干这事,in和out。
Intel汇编语言的形式是:操作码 目的操作数,源操作数。Intel采用这种格式的原因可能是觉得这样表达“目的操作数”=“源操作数”更形象,如同a=6这种形式。
in指令用于从端口中读取数据,其一般形式是:
- 1.in al, dx
- 2.in ax, dx
其中al和ax用来存储从端口获取的数据,dx是指端口号。
这是固定用法,只要用in指令,源操作数(端口号)必须是dx,而目的操作数是用al还是ax,取决于dx端口指代的寄存器是8位宽度还是16位宽度。
out指令用于往端口中写数据,其一般形式是:
- out dx, al
- out dx,ax
- out 立即数, al
- out立即数,ax
注意啦,这和in指令相反,in指令的源操作数是端口号,而out指令中的目的操作数是端口号。
如果上面看着有点凌乱,给大家总结一下in和out指令共性:
- 在以上两个指令中,dx只做端口号之用,无论其是源操作数或目的操作数。
- in指令是从端口读数据,可以认为端口是数据源,所以端口出现在“源操作数”的位置。读出来的数据要有个“目的地”来存放,所以in指令中存放数据的地方出现在“目的操作数”位置。
- out指令是把数据写入端口指向的寄存器,在这里,端口是数据的“目的地”,所以端口出现在目的操作数的位置。待写入的数据总该有个“来源”,所以out指令中的“源操作数”是数据来源。
- 在以上的两个指令中,端口号和数据的位置,是取决于它们各自的角色是源操作数还是目的操作数。
- 在以上两个指令的两个操作数中,无论是对于源操作数还是目的操作数。除端口号外,那个做为数据的操作数(in指令中做为数据目的地,out指令中做为数据源),一律用al寄存器存储8位宽度的数据,用ax寄存器存储16位宽度的数据,至于用al还是ax存数据,是要看端口指向的寄存器宽度是多少,它要和端口寄存器的位宽保持一致,不能丢失数据精度。
- in指令中,端口号只能用dx寄存器。
- out指令中,可以选用dx寄存器或立即数充当端口号。
真心希望大家看完后不会更乱了^_^。
好啦,有了这些硬件相关的知识,对以后我们操作其它硬件来说足够了,我们不需要学习的多全,够用就好。还是那句话,以后用到哪再学不迟,大家辛苦了。
【再续】