汇编实验(中断程序设计)

中断程序设计

首先读一下以下的程序,我们来理解以下代码讲了什么?

STACK SEGMENT PARA 'STACK'
DB 100 DUP(?)
STACK ENDS

DATA SEGMENT
 
DATA ENDS
 
ASSUME DS: SEG1, CS: SEG2	;数据段,代码段
;10
SEG1 SEGMENT
INTOFF DW ?
INTSEG DW ?
SEG1 ENDS
 
SEG2 SEGMENT
START:
	MOV AX, SEG1
	MOV DS, AX
	MOV ES, AX
;21
XOR AX, AX
MOV ES, AX	;开辟ES的拓展空间
CALL STORE
CALL INIT
WAITFOR:
	MOV AH, 01H	;键盘输入并且回显(AL = 输入字符)
	INT 21H		;指令中断(INT 21H),然后T一下,就可以键盘输入了
	CMP AL, 'Q'	;如果是'Q'就是跳转
	JE KEY_Q
	CMP AL, 'I'	;如果为'I'就跳转
	JE KEY_I
	JMP WAITFOR

KEY_Q:
	CALL RESTORE
	MOV AH, 4CH	;带返回码结束(AH = 4CH)
	INT 21H

KEY_I:
	MOV AX, 200H	;输出DX的对应的字符'A'
	MOV BL, 0
	DIV BL
	JMP WAITFOR

STORE:	
	MOV AX, ES:[00H * 4]	;在前面这个ES地址中“:”寻找地址[00H * 4]
	MOV INTOFF, AX
	MOV AX, ES:[00H * 4 + 2]	;分别存进INTOFF与INTSEG中
	MOV INTSEG, AX
	RET

INIT:
	MOV AX, OFFSET NEWINT
	MOV ES:[00H * 4], AX	;先存下NEWINT的后4位所在位置"X:Y"(X)
	MOV AX, SEG NEWINT
	MOV ES:[00H * 4 + 2], AX	;再存下NEWINT的前4位所在地址(Y)
	RET

RESTORE:
	MOV AX, INTOFF
	MOV ES:[00H * 4], AX
	MOV AX, INTSEG
	MOV ES:[00H * 4 + 2], AX
	RET

NEWINT:
	MOV BP, SP
	ADD WORD PTR [BP], 2
	MOV AH, 02H
	MOV DL, 'A'
	INT 21H
	IRET

SEG2 ENDS
	END START

我先写了一些注释。

最开始的时候我们会调用这个STORE

STORE:	
	MOV AX, ES:[00H * 4]	;在前面这个ES地址中“:”寻找地址[00H * 4]
	MOV INTOFF, AX
	MOV AX, ES:[00H * 4 + 2]	;分别存进INTOFF与INTSEG中
	MOV INTSEG, AX
	RET

主要就是先把ES里面的前两个元素存到INTOFF中去,把ES中第三第四个元素存到INTSEG中去,保存之用,因为后面将调用的INIT也会影响到其。

然后就是RET返回去调用(CALL)INIT这个所谓的初始化调用了。

INIT:
	MOV AX, OFFSET NEWINT
	MOV ES:[00H * 4], AX	;先存下NEWINT的后4位所在位置"X:Y"(X)
	MOV AX, SEG NEWINT
	MOV ES:[00H * 4 + 2], AX	;再存下NEWINT的前4位所在地址(Y)
	RET

我们会得到NEWINIT所在的地址,然后按照STORE中的方式那样,我们将原先ES:[0000]到ES:[0003]中的这4个位置,我们拿来存了NEWINIT的开始地址了,所以我们为什么之前用了INTOFF和INTSEG来存,也就是这个道理了。

再者,我们就是去跑一个WAITFOR的循环了,为什么我在这里不去使用WAIT呢?而是使用了WAITFOR,是因为WAIT其实是有这个专有名词的,我还是避开雷区吧。

WAITFOR:
	MOV AH, 01H	;键盘输入并且回显(AL = 输入字符)
	INT 21H		;指令中断(INT 21H),然后T一下,就可以键盘输入了
	CMP AL, 'Q'	;如果是'Q'就是跳转
	JE KEY_Q
	CMP AL, 'I'	;如果为'I'就跳转
	JE KEY_I
	JMP WAITFOR

回到这个看似怎么也跳不出去的循环。

首先讲解以下INT 21H和它的搭档使用的“MOV AH, 01H”。

这两个是搭档使用的,我们INT 21H中,读它的状态,就是由AH位置的状态来转移过来的,这里有个功能表,是它的对应的功能与操作。

INT 21H 指令说明及使用方法(汇编语言学习)可以对应AH功能的学习。

那么,我们现在就知道了,AH等于01H的时候,其实就是键盘输入并且回显的这样一个作用,那么我们如果输入一个字符串,它既不是' I ' 也不是 ' Q ',那么,就会一直重复这个循环。

如果我们输入的是一个' I ',那么,我们会跳转到KEY_I

KEY_I:
	MOV AX, 200H	;输出DX的对应的字符'A'
	MOV BL, 0
	DIV BL
	JMP WAITFOR

首先,我们让AH=02H,这是有何用意呢?我们查表可以知道,02H在“INT 21H”的时候,是用来输出使用的,输出的字符就是DL对应的字符,那么DL的字符应该是从哪里得到呢?我们这时候会去调用到NEWINIT:

NEWINT:
	MOV BP, SP
	ADD WORD PTR [BP], 2
	MOV AH, 02H
	MOV DL, 'A'
	INT 21H
	IRET

我们知道了,DL='A',那么输出的字符也就是‘A’了,返回。

然后我们对应的JMP去返回到WAITFOR中去。

现在看过了输入为' I '的时候,我们再来看看输入为' Q '的时候。

KEY_Q:
	CALL RESTORE
	MOV AH, 4CH	;带返回码结束(AH = 4CH)
	INT 21H

我们呢,会调用这个函数。

这时候我们会先进入RESTORE这个函数,是什么用的呢?我们来看看:

RESTORE:
	MOV AX, INTOFF
	MOV ES:[00H * 4], AX
	MOV AX, INTSEG
	MOV ES:[00H * 4 + 2], AX
	RET

我们中断返回,把原来放在ES[0000]~ES:[0003]的原先的数就给返回回来了,也就是把中断返回的过程了。然后我们RET回来再看。

我们让AH=4CH,查表可以知道,这时候再调用“INT 21H”是带返回码结束的这样一个作用,也就是在这里的时候,我们就退出了循环的操作了。也是结束了。

 


接下去,我们改变了存放的地址,再来看:

我们要做的是编写60H中断程序

将程序改写为响应60H中断请求,并要求使用DOS功能调用的方式设置中断向量。

主要是将原来使用[00H * 4]的地方改成了[60H * 4]。

STACK SEGMENT PARA 'STACK'
DB 100 DUP(?)
STACK ENDS

DATA SEGMENT
 
DATA ENDS
 
ASSUME DS: SEG1, CS: SEG2	;数据段,代码段
;10
SEG1 SEGMENT
INTOFF DW ?
INTSEG DW ?
SEG1 ENDS
 
SEG2 SEGMENT
START:
	MOV AX, SEG1
	MOV DS, AX
	MOV ES, AX
;21
XOR AX, AX
MOV ES, AX	;开辟ES的拓展空间
CALL STORE
CALL INIT
WAITFOR:
	MOV AH, 01H	;键盘输入并且回显(AL = 输入字符)
	INT 21H		;指令中断(INT 21H),然后T一下,就可以键盘输入了
	CMP AL, 'Q'	;如果是'Q'就是跳转
	JE KEY_Q
	CMP AL, 'I'	;如果为'I'就跳转
	JE KEY_I
	JMP WAITFOR

KEY_Q:
	CALL RESTORE
	MOV AH, 4CH	;带返回码结束(AH = 4CH)
	INT 21H

KEY_I:
	INT 60H
	NOP
	JMP WAITFOR

STORE:	
	MOV AX, ES:[60H * 4]	;在前面这个ES地址中“:”寻找地址[00H * 4]
	MOV INTOFF, AX
	MOV AX, ES:[60H * 4 + 2]	;分别存进INTOFF与INTSEG中
	MOV INTSEG, AX
	RET

INIT:
	MOV AX, OFFSET NEWINT
	MOV ES:[60H * 4], AX	;先存下NEWINT的后4位所在位置"X:Y"(X)
	MOV AX, SEG NEWINT
	MOV ES:[60H * 4 + 2], AX	;再存下NEWINT的前4位所在地址(Y)
	RET

RESTORE:
	MOV AX, INTOFF
	MOV ES:[60H * 4], AX
	MOV AX, INTSEG
	MOV ES:[60H * 4 + 2], AX
	RET

NEWINT:
	MOV BP, SP
	ADD WORD PTR [BP], 2
	MOV AH, 02H
	MOV DL, 'A'
	INT 21H
	IRET

SEG2 ENDS
	END START

但是题目中要求的是,让我们使用DOS功能调用的方式设置中断向量。

所以在KEY_I的时候需要作出一些改动(仅改动了KEY_I):

STACK SEGMENT PARA 'STACK'
DB 100 DUP(?)
STACK ENDS
 
DATA SEGMENT
 
DATA ENDS
 
ASSUME DS: SEG1, CS: SEG2	;数据段,代码段
;10
SEG1 SEGMENT
INTOFF DW ?
INTSEG DW ?
SEG1 ENDS
 
SEG2 SEGMENT
START:
	MOV AX, SEG1
	MOV DS, AX
	MOV ES, AX
;21
XOR AX, AX
MOV ES, AX	;开辟ES的拓展空间
CALL STORE
CALL INIT
WAITFOR:
	MOV AH, 01H	;键盘输入并且回显(AL = 输入字符)
	INT 21H		;指令中断(INT 21H),然后T一下,就可以键盘输入了
	CMP AL, 'Q'	;如果是'Q'就是跳转
	JE KEY_Q
	CMP AL, 'I'	;如果为'I'就跳转
	JE KEY_I
	JMP WAITFOR
 
KEY_Q:
	CALL RESTORE
	MOV AH, 4CH	;带返回码结束(AH = 4CH)
	INT 21H
 
KEY_I:
	CLI
	PUSH DS
	MOV DX, OFFSET NEWINT
	MOV AX, SEG NEWINT
	MOV DS, AX
	MOV AH, 60H
	MOV AL, 0
	INT 60H
	POP DS
	STI
 
STORE:	
	MOV AX, ES:[60H * 4]	;在前面这个ES地址中“:”寻找地址[00H * 4]
	MOV INTOFF, AX
	MOV AX, ES:[60H * 4 + 2]	;分别存进INTOFF与INTSEG中
	MOV INTSEG, AX
	RET
 
INIT:
	MOV AX, OFFSET NEWINT
	MOV ES:[60H * 4], AX	;先存下NEWINT的后4位所在位置"X:Y"(X)
	MOV AX, SEG NEWINT
	MOV ES:[60H * 4 + 2], AX	;再存下NEWINT的前4位所在地址(Y)
	RET
 
RESTORE:
	MOV AX, INTOFF
	MOV ES:[60H * 4], AX
	MOV AX, INTSEG
	MOV ES:[60H * 4 + 2], AX
	RET
 
NEWINT:
	MOV BP, SP
	ADD WORD PTR [BP], 2
	MOV AH, 02H
	MOV DL, 'A'
	INT 21H
	IRET
 
SEG2 ENDS
	END START

 

  • 12
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wuliwuliii

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值