int指令的最终功能和call指令类似,都是调用一段程序
两者的根本区别表现在服务时间和服务对象上不一样。(本段叙述参考原文:http://blog.csdn.net/jxq0816/article/details/50121563)
1)调用子程序发生的时间是已知的和固定的,即在主程序的调用指令(CALL)执行时发生主程序调用子程序过程,调用指令所在位置是已知的和固定的;而中断过程发生的时间一般是随机的,CPU在执行某一主程序时受到中断源提出的中断申请,就发生中断过程,而中断申请一般由硬件电路产生,申请时间是随机的。也可以说,调用子程序是程序设计者事先安排好的,而执行中断服务程序是由系统工作环境随机决定的。
2)子程序完全为主程序服务,两者属于主从关系。主程序需要子程序时就去调用子程序,并把调用结果带回主程序继续执行。而中断服务程序与主程序二者一般是无关的,两者是平行关系。
3)主程序调用子程序的过程完全属于软件处理过程,不需要专门的硬件电路,而中断处理系统是一个软、硬件结合的系统,需要专门的硬件电路才能完成中断处理的过程。
4)子程序嵌套可以实现若干级,嵌套的最多级数受计算机内存开辟的堆栈大小限制;而中断嵌套级数主要由中断优先级来决定,一般优先级不会很大。
从宏观上看,虽然程序中断方式克服了程序查询方式中CPU"踏步"现象,实现了CPU与IO并行工作,提高了CPU的资源利用率,但从微观操作分析,CPU在处理中断程序时,仍需暂停原程序的正常运行,尤其是当高速I/O设备或辅助存储器频繁地、成批地与主存交换信息时,需不断打断CPU执行现行程序,而执行中断服务程序。
在完成这个实验时,可参看下面相关的附注实验。
(1)
安装程序:
assume cs:codesg codesg segment
start: mov ax, cs mov ds, ax mov si, offset show_str ;设置ds:si指向源地址 mov ax, 0 mov es, ax mov di, 200h ;设置es:si指目的地址 mov cx, offset show_strend - offset show_str ;设置cx传输长度 cld rep movsb mov ax, 0 ;设置中断向量表 mov es, ax mov word ptr es:[7ch*4], 200h mov word ptr es:[7ch*4+2], 0 mov ax, 4c00h int 21h ;-------show_str---------------
show_str: push si push di push cx push bx mov bl, cl mov ax, 0b800h mov es, ax mov di, 0 mov al, 160 mul dh mov di, ax mov al, 2 ;es:di point to display memory mul dl add di, ax s: xor cx, cx mov cl, ds:[si] jcxz ok mov es:[di+0], cl mov es:[di+1], bl add si, 1 add di, 2 jmp s ok: pop bx pop cx pop di pop si iret show_strend:nopcodesg ends
end start
应用程序:
assume cs:codedata segmentdb 'welcome to masm!', 0
data endscode segment
start: mov dh, 10mov dl, 10mov cl, 2mov ax, datamov ds, axmov si, 0int 7chmov ax, 4c00hint 21hcode ends
end start
实验结果:
体会:show_str既可以用call子程序方式来调用,也可以用中断的方式来调用,这两者有各自的特点和用途,本篇开头已经略述。
(2)
附三中已经有类似实现,这里略去。
(3)下面的程序,分别在屏幕的第2,4,6,8行显示4句英文诗,补全程序。
代码如下:
assume cs:code ;不写start,默认从cs:0开始读取指令code segment
s1: db 'Good,better,best,','$'
s2: db 'Never let it rest,','$'
s3: db 'Till good is better,','$'
s4: db 'And better,best.','$'
s: dw offset s1,offset s2,offset s3,offset s4
row: db 2,4,6,8start: mov ax, csmov ds, axmov bx, offset smov si, offset rowmov cx, 4ok: mov bh, 0mov dh, ds:[si]mov dl, 0mov ah, 2int 10hmov dx, ds:[bx]mov ah, 9int 21hadd bx, 2inc siloop okmov ax, 4c00hint 21hcode ends
end start
实验结果:
实验体会:
这个才是在现实中解决问题的方式--》用别人已经造好的轮子。世界要靠大家的合作才能更好的发展,自己直接用别人的轮子即可;但是首先你好了解别人的轮子是怎么造的,完全不理会原理而只会使用,有可能被组装出来的“汽车”非常的难用。总之,研究其理,用其产品。
附一:编写,安装中断7ch中断例程,实现word型数据求平方(课本253页)
1,安装程序代码:
assume cs:codesg codesg segment
start: mov ax, cs mov ds, ax mov si, offset sqr ;设置ds:si指向源地址 mov ax, 0 mov es, ax mov di, 200h ;设置es:si指目的地址 mov cx, offset sqrend - offset sqr ;设置cx传输长度 cld rep movsb mov ax, 0 ;设置中断向量表 mov es, ax mov word ptr es:[7ch*4], 200h mov word ptr es:[7ch*4+2], 0 mov ax, 4c00h int 21h ;sqr------------------------
sqr: mul axiret
sqrend: nopcodesg ends
end start
2,应用代码
assume cs:codesgcodesg segment
start: mov ax, 3456int 7chadd ax, axadc dx, dxmov ax, 4c00hint 21hcodesg ends
end start
3,实验结果
附二:编写,安装中断7ch中断例程,实现字符串字母全变成大写(课本254页)
1,安装程序代码:
assume cs:codesg codesg segment
start: mov ax, cs mov ds, ax mov si, offset capital ;设置ds:si指向源地址 mov ax, 0 mov es, ax mov di, 200h ;设置es:si指目的地址 mov cx, offset capitalend - offset capital ;设置cx传输长度 cld rep movsb mov ax, 0 ;设置中断向量表 mov es, ax mov word ptr es:[7ch*4], 200h mov word ptr es:[7ch*4+2], 0 mov ax, 4c00h int 21h ;capital------------------------
capital:push cxpush si
change: mov cl, [si]mov ch, 0jcxz okand byte ptr [si], 11011111binc sijmp short changeok: pop sipop cxiretcapitalend:nop
codesg ends
end start
2,应用程序
assume cs:codesgdata segmentdb 'conversation', 0
data endscodesg segment
start: mov ax, datamov ds, axmov si, 0int 7chmov ax, 4c00hint 21hcodesg ends
end start
3,实验结果
附三:编写,安装中断7ch中断例程,实现loop指令功能(课本256页)
1,安装程序
assume cs:codesg codesg segment
start: mov ax, cs mov ds, ax mov si, offset lp ;设置ds:si指向源地址 mov ax, 0 mov es, ax mov di, 200h ;设置es:si指目的地址 mov cx, offset lpend - offset lp ;设置cx传输长度 cld rep movsb mov ax, 0 ;设置中断向量表 mov es, ax mov word ptr es:[7ch*4], 200h mov word ptr es:[7ch*4+2], 0 mov ax, 4c00h int 21h ;lp------------------------
lp: mov bp, spdec cxjcxz lpretadd [bp+0], bx
lpret: iret
lpend: nopcodesg ends
end start
2,应用程序
assume cs:codesg codesg segment
start: mov ax, 0b800hmov es, axmov di, 160*12mov bx, offset s - offset semov cx, 8
s: mov byte ptr es:[di], '!'add di, 2int 7ch
se: nopmov ax, 4c00h int 21h codesg ends
end start
3,实验结果
附四:调用BIOS中断例程
int10中断例程是bios提供的中断例程,其中包含了多个和屏幕输出相关的子程序,确定子程序要通过ah来传递内部子程序的编号,代码如下:
assume cs:codesg codesg segment
start: mov ah, 9mov al, 'a'mov bl, 11001010bmov bh, 0mov cx, 3int 10hmov ax, 4c00h int 21h codesg ends
end start
实验结果:
附五:调用dos中断例程,在屏幕的第5行12列显示字符串“Welcome to masm!”
mov ax, 4c00h
int 21h
int 21h中断例程是dos提供的中断例程,其中包含了dos提供给程序员在编程时调用的子程序。int 21h中断例程的4ch号子程序是返回功能。
(ah)=9表示调用第21h号中断例程的第9号子程序,功能为在光标位置显示字符串,可以提供要显示的字符串的地址作为参数。
代码如下:
assume cs:codesg data segmentdb 'Welcome to masm!', '$'
data endscodesg segment
start: mov ah, 2 ;置光标mov bh, 0 ;第0页mov dh, 5 ;dh行mov dl, 12 ;dl列int 10h ;BIOS中断mov ax, datamov ds, axmov dx, 0 ;point to first address of datamov ah, 9int 21hmov ax, 4c00h int 21h codesg ends
end start
实验结果:
从实验四,五可以看出,遇到打印相关的需求,直接调用BIOS,操作系统的相关中中断例程即可,无需自己再造轮子。