8086汇编学习笔记17

端口

系列文章

在PC机中,和CPU通过总线相连的芯片除了各种存储器外,还有以下3中芯片:

  1. 各种接口卡(例如网卡、显卡)上的接口芯片,它们控制接口卡工作
  2. 主板上的接口芯片,CPU通过它们对部分外设进行访问
  3. 其它芯片,用来存储相关的系统信息,或处理相关的输入输出

这些芯片中都有一组可以由CPU读写的寄存器,这些寄存器在物理上可能处于不同的芯片中,它们在以下两点上相同:

  1. 通过它们所在的芯片,和CPU的总线相连
  2. CPU对它们读写的时候,都通过控制线向它们所在的芯片发出端口读写指令

从CPU角度,将这些寄存器都当做端口,对它们进行统一编址,从而建立一个统一的端口地址空间,每一个端口在地址空间中都有一个地址。

CPU可以直接读写以下3个地方的数据:

  1. CPU内部的寄存器
  2. 内存单元
  3. 端口

本节关于端口的读写。

端口的读写

在访问端口的时候,CPU通过端口地址来定位端口。端口所在的芯片和CPU通过总线相连,因此端口地址和内存地址一样,通过地址总线来传送。

在PC系统中,CPU最多可以定位64KB个不同的端口,则端口地址的范围为0~65535.

端口的读写指令只有以下两条:

IN指令(端口输入指令)
格式:
IN container , port
用途:
从端口 port 处读入一个字节至 container 处。
OUT指令(端口输出指令)
格式:
OUT port , container
用途:
container 处写入一个字节至端口 port 处。

访问端口时,与总线的相关操作如下:

  1. CPU通过地址线将端口地址信息发出
  2. CPU通过控制线发出端口读命令,选中端口所在的芯片,并通知它将要从中读取数据
  3. 端口所在的芯片将对应端口中的数据通过数据线送入CPU

INOUT 指令中,只能使用 AXAL 来存放从端口中读取的数据或要发送到端口中的数据:访问8位端口时用 AL ,访问16位端口时用 AX

汇编指令SHL和SHR

SHLSHR 是逻辑移位指令。

SHL指令(逻辑左移指令)
格式:
SHL container , bit
用途:
将一个寄存器或内存单元 container 的数据向左移 bit 位,最后移出的一位写入 CF 中,最低位用0补充。

如果移动位数大于1时,必须将移动位数放在 CL 寄存器中

指令:

mov al, 01010001B
mov cl, 3
shl al, cl

AL 的数据左移3位,移位后 (AL)=10001000BCF=0

shl al, 1

AL 的数据左移1位,移位后 (AL)=00010000BCF=1

可以看出,将N左移一位,相当于执行N=N×2,由此产生的进位存储在 CF 标志中。

SHR指令(逻辑右移指令)
格式:
SHR container , bit
用途:
将一个寄存器或内存单元 container 的数据向右移 bit 位,最后移出的一位写入 CF 中,最高位用0补充。

SHRSHL 所进行的操作相反,其余相同。

可以看出,将N右移一位,相当于执行N=N÷2。右移位数大于1时,必须将移动位数放在 CL 寄存器中。

CMOS RAM芯片

PC机中,有一个CMOS RAM芯片(一般简称为CMOS),此芯片的特征如下:

CMOS RAM存储的时间信息

CMOS RAM中存放着当前的时间:年、月、日、时、分、秒,这6个信息的长度都为1个字节,存放单元为:

秒:0分:2时:4日:7月:8年:9

这些数据以BCD码的形式存放。

BCD码是以4位二进制数表示的十进制数码的编码方式,如下所示:

一个字节可以表示两个BCD码,即CMOS RAM存储时间信息的单元中,存储了两个用BCD码表示的两位十进制数,高4位的BCD码表示十位,低4位的BCD码表示个位

以下程序段在屏幕中间显示当前的月份:

从CMOS RAM的8号单元读出当前月份的BCD码。过程分两步:首先向地址端口70H写入单元地址8,再从数据端口71H中取得指定单元的数据:

mov al, 8
out 70h, al ; write address info to 70h port
in al, 71h  ; get data from 71h port

将从CMOS RAM的8号单元中读出的第一个字节,分为两个表示BCD码值的数据。以上程序段使用移位和掩码分别取得高4位和低4位:

mov ah, al        ; (AL) is the data from CMOS RAM [8]
mov cl, 4
shr ah, cl        ; (AH) is the tens of month
and al, 00001111B ; (AL) is the ones of month

最后,在屏幕上中间位置显示对应的字符。将数据加上30H是为了将数字转化为对应的字符:

add ah, 30h
add al, 30h
mov bx, 0b800h
mov es, bx
mov byte ptr es: [2000], ah ; show the tens of month
mov byte ptr es: [2002], al ; show the ones of month