汇编输入输出程序设计学习笔记
说明,只是个人的学习笔记,不足之处多多,不适合作学习的资料,
希望高手指导,不胜感激,文中标明金州注释的地方,是个人见解,
注意有可能是错误的。
I/O设备数据传输方式,
1.查询方式
2,中断方式
3.DMA方式,(直接存储器存取方式)
汇编的好处之一是能控制硬件
例如 循环测试状态寄存器的第2位是否为1
AGAIN IN AL, 27H (假设端口号位27H,很显然是8位的寄存器,金州注释)
TEST AL, 00000100B
JZ AGAIN (如果第2位是0,循环测试,继续,金州注释)
(状态寄存器就是看看硬件的状态,比如打印机是不是有纸等等,金州注释 )
例如2,SOUND程序(扬声器)
.......
mov dx, 100 (赋予值100,金州注释)
in al, 61h (读出内容,金州注释)
and al, 11111100b(设置0,金州注释)
sound: xor al, 2 (2的二进制是10,异或,就是10变化,金州注释)
out 61h, al (输出,金州注释)
mov cx, 140h (延时,金州注释)
wait1: loop wait1 (循环,金州注释)
dec dx
jne sound
.......
(原理是01交替中断形成电波,发出声音,I/O汇编,金州注释)
例如3。
打印机查询输出子程序
print proc near
push ax (压入堆栈,金州注释)
push dx
mov dx, 378h (378h数据寄存器端口,大于256,先送入dx,金州注释 )
out dx, al
mov dx, 379h (379h状态寄存器端口,金州注释)
again:in al, dx
test al, 80h
je again (如果忙,循环查询,直到不忙,执行下面就是打印,金州注释)
mov dx, 37ah (37ah控制寄存器端口,金州注释)
mov al, 0dh
out dx, al (送入37ah,就是送个信号,金州注释)
jmp $+2 (两个字节,就是下面的命令,起到延时作用,金州注释)
mov al, och
out dx, al
pop dx (出堆栈,打印完成,金州注释)
pop ax
ret
print endp
下面说说中断传送方式,这个比较用得多
(算是重点了,金州注释:)))
中断源,(引起中断的事件,金州注释)
外中断(硬件中断,金州注释)
1.外设的I/O请求, ——可屏蔽中断
(就是可以相应也可以不响应,金州注释)
2,电源掉了/奇偶错误——非屏蔽中断
(就是必须响应,不可能不响应是不是,奇偶举一个例子
比如溢出了,金州注释)
内中断(软件问题,金州中断)
INT指令(80X86或者8088可处理256个中断,金州注释)
CPU错误(比如溢出,金州注释)
对调试程序设置的中断(你自己设置的,金州注释)
例如,为中断类型N设置中断向量
.......
MOV AX, 0 (把0付给AX,金州注释)
MOV ES, AX
MOV BX, N*4
MOV AX, OFFSET INTHAND
MOV ES: WORD PTR, AX (偏移地址,N*4,金州注释)
MOV AX, SEG INTHAND
MOV ES: WORD PTR, AX
.......
INTHAND: (表示是一个中断处理程序,金州注释)
...
IRET
(看出来了吧,间接寻址,设置成功了,可以调用了,RNT N ,金州注释)
DOS功能调用,21H存取中断向量
设置中断向量
AH=25H
AL=中断类型号
DSX=中断向量
INT 21H
取中断向量
AH=35H (功能号,35H, 金州注释)
AL=中断类型号
INT 21H
返回时送ES:BX=中断向量 (放入ES,BX,就是往这里找,金州注释)
(以上不用多解释了吧,就是格式,金州注释)
例如,用DOS功能调用存取中断向量,
MOV AL, N
MOV AH, 35H
INT 21H (以上取N的中断向量,金州注释)
PUSH ES (压入堆栈,原因为了用后恢复,金州注释)
PUSH BX
PUSH DS (DS经常需要用到,先压入,金州注释)
MOV AX, SEG INTHAND (设置新的中断向量,金州注释)
MOV DS, AX
MOV DX, OFFSET INTHAND
MOV AL, N
MOV AH, 25H
INT 21H (设置新的中断完毕,金州注释)
POP DS
..........
POP DX (出堆栈,恢复原来的,金州注释)
POP DS
MOV AL, N
MOV AH, 25H
INT 21H (原来的恢复完毕,金州注释)
...
INTHAND:
...
IRET
(注意已经恢复原来的,如果这个时候INT 21H,将使用原来的,金州注释)
中断程序的编写步骤,(也许没有必要写出来,为了更清晰给一起学习的朋友
列出来吧,金州注释)
主程序:
1设置中断向量
2设置CPU的中断允许位 IF
3设置设备的中断屏蔽位
中断处理子程序
1保存寄存器内容
2如果允许中断嵌套,则开中断
3处理中断
4关闭中断
5送中断结束命令,EIO,给中断命令寄存器 (不送可能死机啊,注意,金州注释)
6恢复寄存器内容
7,IRET中断返回
(应该主要就这些,子程序的编写问题可以见我的子程序学习笔记,金州注释,)
例如,编写一个中断处理程序,要求是在主程序运行期间,每隔10秒钟响铃一次
并显示‘zjz1’
.model small(小模式,金州注释,)
.stack (缺省堆栈,金州注释)
.data
cnt dw 1
mes db 'zjz1',0ah,0dh,'$'(以上数据段,金州注释)
.code (代码段,金州注释)
main proc far
start:
mov ax,@data (以下是赋予值,不一一解释,金州注释)
mov ds, ax
mov al, 1ch
mov ah, 35h
int 21h
push es (压入堆栈,以下和上一个例子类似,金州注释)
push bx
push ds
mov dx, offset ring
mv ax, seg ring
mov ds, ax
mov al, 1ch
mov ah, 25h
int 21h
pop ds
inal, 21h
and al, 11111110b (21h的0位是控制器,设置为0,才允许,金州注释)
out 21h, al
sti
mov di 30000 (其实就是一个延时,金州注释)
dly: mov si, 60000
dly1:
dec si (以下是一个双循环,就是控制程序时间,金州注释)
jnz dly1
dec di (可以调整si,di的数值,如果大,就是显示时间长,金州注释)
jnz dly
pop dx (出堆栈,恢复以前的,金州注释)
pop ds
mov al, 1ch
mov ah, 25h
int 21h (这一段是恢复,和上一个例子类似,金州注释)
mov ax, 4c00h(以下返回操作系统,结束程序,金州注释)
int 21h
main endp
ring proc near(以下是关键子程序,金州注释)
.....
mov ax, @data (赋予值,金州注释)
mov ds, ax
sti
dec cnt (给cnt减1,就是变成0,金州注释)
jnz exit (不等于0退出,其实等于,所以输出,金州注释)
mov dx, offset mes
mov ah, 09
int 21h
call sound
mov cnt, 182 (cnt 赋予值182了,金州注释)
exit: cli
.....
iret
ring endp
end start
(大家看懂了吧,就是把cnt赋予值182,然后逐渐减少1,到了0就显示,
就达到了要求,因为开始的时候赋予值是1,所以开始就显示,然后等10
秒,如果开始赋予值182,则开始不显示,过10秒显示,自己随便改着玩吧
因为修改不是外设,从端口号可以知道,所以不用送结束命令,金州注释)
页:
[1]