程序说明:
这是PC机间相互通信的例子,程序“require”为用查询方式实现,程序“interrupt”为用中断方式实现。
流程图:
源程序:
require.asm
CODE SEGMENT
ASSUME CS: CODE
START:
;初始化波特率除数寄存器
MOV DX , 3FBH ;指向线路控制寄存器
MOV AL , 80H ;位7置1
OUT DX , AL ;发送此字节
MOV DX , 3F9H ;指向波特率除数的最高有效位
MOV AL , 0 ; 1200 BPS对应的最高有效位
OUT DX , AL ;发送此字节
DEC DX ;指向波特率除数的最低有效位
MOV AL , 60H ; 1200 BPS对应的最低有效位
OUT DX , AL ;发送此字节
;初始化线路控制寄存器:
MOV AL , 1BH ;数据长度为8位 , 1个奇偶校验位 , 偶校验 , 1个停止位
MOV DX , 3FBH ;指向线路控制寄存器
OUT DX , AL ;发送此字节
;初始化中断允许寄存器
MOV DX , 3F9H ;指向中断允许寄存器
MOV AL , 0 ;禁止所有中断
OUT DX , AL ;发送字节
READ: ;线路状态检测循环
MOV DX , 3FDH ;指向线路状态寄存器
IN AL , DX ;取状态字节
TEST AL , 1EH ;检查错误
JNZ ERROR ;若出错则转错误处理例程
TEST AL , 01H ;测试是否已收到数据
JNZ RECEIVE ;转接收例程
TEST AL , 20H ;测试是否可以发送字符
JNZ SEND ;若是转发送例程
JMP READ ;循环检测
SEND: ;发送字符(来自键盘):
MOV AH , 1 ;BIOS功能用以检测是否有字符可读
INT 16H ;BIOS键盘中断
JZ READ ;若无击键则返回循环
MOV AH , 0 ;BIOS功能用于取击键码
INT 16H ;击键码现在AL中
CMP AL , 03H ;检测CTRL+C
JZ EXIT ;若是 , 转EXIT处结束程序
MOV DX , 3F8H ;指向发送保持寄存器
OUT DX , AL ;发送字符
JMP READ ;返回循环
RECEIVE: ;接收数据(在屏幕上显示):
MOV DX , 3F8H ;接收数据寄存器
IN AL , DX ;取新收到的字符
CMP AL , 03H ;检测CTRL+C
JZ EXIT ;若是 , 转EXIT处结束程序
MOV DL , AL ;准备显示字符
MOV AH , 2 ;用于显示字符的DOS中断
INT 21H ;显示字符
CMP AL , 0DH ;判断刚才收到的字符是否为回车
JNZ READ ;不是,转线路检测循环
MOV DL , 0AH ;若是,则加显示一个换行符
MOV AH , 2
INT 21H
JMP READ ;返回线路检测循环
ERROR: ;出错处理,显示一个提示
PUSH CS
POP DS
MOV DX , OFFSET ERROR_MESSAGE
MOV AH , 9
INT 21H
EXIT: ;程序退出
MOV AH , 4CH
INT 21H
ERROR_MESSAGE DB 0AH , 'ERROR!$' ;定义出错时显示的提示
CODE ENDS
END START
interrupt.asm
;代码段
CODE SEGMENT
ASSUME CS: CODE
NEW_INT: ;接收字符的中断处理程序
STI ;CPU开中断
;CLI将IF置0,屏蔽掉“可屏蔽中断”,当可屏蔽中断到来时CPU不响应,继续执行原指令
;STI 与之相反,STI将IF置1,允许“可屏蔽中断”,中断到来转而处理中断
MOV DX , 3F8H ;接收字符
IN AL , DX ;从dx端口接受内容到al
MOV DL , AL ;显示接收字符
MOV AH , 2
INT 21H
CMP DL , 0DH ;判断是否为回车
JNZ L2 ;不是,转L2处
MOV DL , 0AH ;若是,加显示一个换行符
MOV AH , 2
INT 21H
L2:
MOV AL , 20H ;发中断结束命令(EOI)
OUT 20H , AL ;将al值写入20h
IRET
START: ;主程序部分
MOV AH , 35H
MOV AL , 0CH ;中断号
INT 21H ;读取原0CH号中断服务程序的地址
PUSH BX
PUSH ES ;以上地址入栈保存(以便在程序退出时再恢复中断矢量表中的内容)
MOV AX , CS
MOV DS , AX
MOV DX , OFFSET NEW_INT
MOV AH , 25H
MOV AL , 0CH
INT 21H ;修改中断矢量表,将NET_INT位置登记为0CH号中断服务程序的地址
;以下初始化8250
MOV DX , 3FBH ;指向线路控制寄存器
MOV AL , 80H ;位7置1
OUT DX , AL ;发送此字节
MOV DX , 3F9H ;指向波特率除数的高字节
MOV AL , 0 ; 1200 BPS对应的高字节
OUT DX , AL ;发送此字节
DEC DX ;指向波特率除数的低字节
MOV AL , 60H ; 1200 BPS对应的低字节
OUT DX , AL ;发送此字节
MOV AL , 1BH ;数据长度为8位 , 1个奇偶校验位 , 偶校验 , 1个停止位
MOV DX , 3FBH ;指向线路控制寄存器
OUT DX , AL ;发送此字节
MOV DX , 3FCH ;设置MODEM控制寄存器
MOV AL , 0BH ;允许8250发中断
OUT DX , AL
MOV DX , 3F9H ;指向中断允许寄存器
MOV AL , 1 ;允许数据接收准备好中断
OUT DX , AL ;发送此字节
CLI ;关中断,以便对中断控制器8259A进行操作
IN AL , 21H ;读取中断屏蔽寄存器的内容
AND AL , 0EFH ;将COM1中断(即IRQ4引脚)的对应位置0,允许中断。
OUT 21H , AL ;写入中断控制器8259A中
STI ;开中断
L1: ; 主程序循环,等待收到字符的中断发生。
MOV AH , 0
INT 16H ;读取键盘字符
CMP AL , 03 ;比较是否为CTRL-C键
JNZ L1 ;若不是,继续循环
EXIT: ;退出处理
MOV AH , 25H
MOV AL , 0CH
POP DS
POP DX
INT 21H ;恢复中断矢量表中0CH号中断服务程序的原地址。
MOV AH , 4CH
INT 21H ;返回DOS
CODE ENDS
END START
函数功能
INTERRUPT程序通过替换DOS中断中0CH号中断的处理程序,实现对字符收发的响应。接收到字符后进行显示。当程序结束后,恢复原中断处理程序。
REQUIRE程序通过循环检测端口状态来实现对字符收发的响应。通过读取状态字节,跳转执行对应的操作。
参数传递
本题无参数传递
中断向量计算
以REQUIRE程序为例,程序使用了10H、16H函数库的函数调用。
10H号函数库:CS=410h+2h=42h , IP=410h=40h 。中断向量为0:40H。
16H号函数库:CS = 416H + 2H =60H, IP =416H=58H。中断向量为0:58H。