端口
端口的概念
CPU 可以直接读写的地址空间:
- 内存地址空间:连接内存芯片
- 端口地址空间:连接各种接口芯片(键盘控制器、磁盘控制器、CMOS RAM 等)
接口芯片内部有寄存器,CPU 通过端口地址读写这些寄存器,间接控制外设。
端口地址范围:0~65535(共 64KB 个端口)
类比:端口 ≈ 设备的"寄存器窗口",CPU 通过 I/O 地址总线访问,与内存总线分离。
in 和 out 指令
端口读写只能用专用指令,不能用 mov。
从端口读数据
asm
; 端口号 ≤ 255:直接写端口号
in al, 60h ; 从 60h 端口读 1 字节到 al
; 端口号 > 255:端口号必须放在 dx 中
mov dx, 3f8h
in al, dx ; 从 3F8h 端口读 1 字节到 al
in ax, dx ; 从 3F8h 端口读 2 字节到 ax向端口写数据
asm
out 70h, al ; 将 al 写入 70h 端口
mov dx, 3f8h
out dx, al ; 将 al 写入 dx 指向的端口注意:
in/out只能用al(8位)或ax(16位)作为数据寄存器。
CMOS RAM 芯片
CMOS RAM 用于保存实时时间和硬件配置,由电池供电,关机后数据不丢失。
- 容量: 128 字节
- 端口:
70h:地址端口(写入要访问的字节索引)71h:数据端口(读出该字节的值)
访问方法:
asm
; 读 CMOS RAM 的第 N 个字节
mov al, N ; N = 字节索引
out 70h, al ; 告诉芯片:我要访问第 N 个字节
in al, 71h ; 读取数据CMOS 时间数据单元(部分):
| 偏移 | 含义 |
|---|---|
| 0 | 秒 |
| 2 | 分 |
| 4 | 时 |
| 7 | 日 |
| 8 | 月 |
| 9 | 年(后两位) |
注意:所有值以 BCD 码存储。BCD 码:高 4 位=十位,低 4 位=个位。例如
0x23= 23,不是十进制的 35。
shl 和 shr 指令(移位)
asm
shl 目标, 移位数 ; 逻辑左移(高位移入 CF,低位补 0)
shr 目标, 移位数 ; 逻辑右移(低位移入 CF,高位补 0)移位数可以是立即数 1,或 cl 寄存器中的值(8086规定):
asm
mov al, 01010001b
shl al, 1 ; 左移1位:10100010b,移出位→CF=0
mov cl, 3
shr al, cl ; 右移3位应用:合并 BCD 码的十位和个位
asm
; 读出月份(BCD码),分解为两位数字显示
in al, 71h ; al = BCD月份,如 06h = 6月
mov ah, al
mov cl, 4
shr ah, cl ; ah = 十位(高4位 → 低4位)
and al, 0fh ; al = 个位(低4位)
add ax, 3030h ; 转为 ASCII 码('0' = 30h)实战示例:读取 CMOS 时间(月份)
asm
assume cs:code
code segment
start:
; 读取月份(单元 8)
mov al, 8
out 70h, al
in al, 71h ; al = BCD月份
; BCD → 两个 ASCII 字符
mov ah, al
mov cl, 4
shr ah, cl ; 十位
and al, 0fh ; 个位
add ax, 3030h ; 转 ASCII
; 在屏幕 0 行 0 列显示
mov bx, 0b800h
mov es, bx
mov es:[0], ah ; 十位字符
mov byte ptr es:[1], 07h ; 颜色:白色
mov es:[2], al ; 个位字符
mov byte ptr es:[3], 07h
mov ax, 4c00h
int 21h
code ends
end start