汇编--int指令

中断信息可以来自CPU的内部和外部, 当CPU的内部有需要处理的事情发生的时候,将产生需要马上处理的中断信息,引发中断过程。在http://t.csdn.cn/jihpG,我们讲解了中断过程和两种内中断的处理。

这一章中, 我们讲解另一种重要的内中断, 由int指令引发的中断。

int指令

int指令的格式为:int n

n为中断类型码, 它的功能是引发中断过程。

CPU执行int n指令, 相当于引发一个n号中断的中断过程, 执行过程如下:

(1)取中断类型码n;

(2)标志寄存器入栈,IF=0,TF=0;

(3)CS、IP入栈;

(4)(IP)=(n*4),(CS)=(n*4+2)

可以在程序中使用int指令调用任何一个中断的中断处理程序。例如, 下面的程序:

这个程序在DOS方式下执行时, 将在屏幕中间显示一个"!",然后显示"Divide overflow"后返回到系统中。"!"是我们编程显示的, 而"Divide overflow"是哪里来的呢?我们的程序中又没有做除法, 不可能产生除法溢出。

程序是没有做除法, 但是在结尾使用了int 0指令。CPU执行int 0指令时, 将引发中断过程, 执行0号中断处理程序, 而系统设置的0号中断处理程序的功能是显示"Divide overflow", 然后返回到系统。

一般情况下,系统将一些具有一定功能的子程序,以中断处理程序的方式提供给应用程序调用。我们在编程的时候, 可以用int指令调用这些子程序。当然, 也可以自己编写一些中断处理程序供别人使用。以后,我们可以将中断处理程序简称为中断例程。

编写供应用程序调用的中断例程

前面,我们已经编写过中断0的中断例程了,现在我们讨论可以供应用程序调用的中断例程的编写方法。下面通过两个问题来讨论。

问题一:编写、安装中断7ch的中断例程。

功能:求一word型数据的平方。

参数:(ax)=要计算的数据。

返回值:dx、ax中存放结果的高16位和低16位。

应用举例:求:2*3456^2。

分析一下,我们要做以下3部分工作。

(1)编写实现求平方功能的程序;

(2)安装程序,将其安装在0:200处;

(3)设置中断向量表,将程序的入口地址保存在7ch表项中,使其成为中断7ch的中断例程。

安装程序如下:

复制代码
assume cs:code

code segment 
 start:  
	    ;安装sqr程序
		mov ax,cs 
		mov ds,ax
		mov si,offset sqr   ;设置ds:si指向源地址
		mov ax,0
		mov es,ax 
		mov di,200h   ;设置es:di指向目的地址
		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:mul ax   ;求平方
		iret
		
 sqrend:nop
	       
	   
code ends
end start

注意, 在中断例程sqr的最后, 要使用iret指令。

用汇编语法描述, iret指令的功:

pop IP

pop cs

popf

CPU执行int 7ch指令进入中断例程之前, 标志寄存器、当前的CS和IP被压入栈中, 在执行完中断例程后, 应该用iret指令恢复int 7ch执行前的标志寄存器和CS、IP的值,从而接着执行应用程序。

int指令和iret指令的配合使用与call指令和ret指令的配合使用具有相似的思路。

对int、iret和栈的深入理解

问题:用7ch中断例程完成loop指令的功能。

loop s的执行需要两个信息, 循环次数和到s的位移, 所以, 7ch中断例程要完成loop指令的功能, 也需要这两个信息作为参数。我们用cx存放循环次数, 用bx存放位移。

应用举例:在屏幕中间显示80个'!'

复制代码
assume cs:code

code segment 
 start:  
	    ;
		mov ax,0b800h 
		mov es,ax
		mov di,160*12+0
		mov bx,offset s-offset se ;计算从标号s到标号se的转移位移
		mov cx,80
	  s:mov byte ptr es:[di], '!'
		add di,2
		int 7ch   ;如果(cx)≠0,转移到标号s处,就是完成loop s的功能

	 se:nop
	
		mov ax,4c00h 
		int 21h
       
	   
code ends
end start

在上面的程序中, 用int 7ch调用7ch中断例程进行转移, 用bx传递转移的位移。

分析:为了模拟loop指令, 7ch中断例程应具备下面的功能:

(1)dec cx;

(2)如果(cx)≠0,转到标号s处执行,否则向下执行。

下面我们分析7ch中断例程如何实现到目的地址的转移。

(1)转到标号s显然应设(CS)=标号s的段地址,(IP)=标号s的偏移地址。

(2)那么,中断例程如何得到标号s的段地址和偏移地址呢?

int 7ch引发中断过程后, 进入7ch中断例程, 在中断过程中, 当前的标志寄存器、CS和IP都要压栈,此时压入的CS和IP中的内容,分别是调用程序的段地址(可以认为是标号s的段地址) 和int 7ch后一条指令的偏移地址(即标号se的偏移地址) 。

可见,在中断例程中,可以从栈里取得标号s的段地址和标号se的偏移地址,而用标号se的偏移地址加上bx中存放的转移位移就可以得到标号s的偏移地址。

(3)现在知道,可以从栈中直接和间接地得到标号s的段地址和偏移地址,那么如何用它们设置CS:IP呢?

可以利用iret指令, 我们将栈中的se的偏移地址加上bx中的转移位移, 则栈中的se 的偏移地址就变为了s的偏移地址。我们再使用iret指令, 用栈中的内容设置CS、IP, 从而实现转移到标号s处。

7ch中断例程如下。

复制代码
      lp:push bp 
	     mov bp,sp 
		 dec cx 
		 jcxz lpret ;cx=0就转移
		 add[bp+2],bx ;产生中断时,pushf  push cs  push ip,进入中断程序后又push bp
		              ;(bp+2)就是se标号ip
					  ;(bp+2)加上位移bx就是s的偏移地址
					  ;之后iret过程中pop ip获取的就是s的偏移地址
   lpret:pop bp 
         iret

BIOS和DOS中断例程的安装过程

前面的课程中,我们都是自己编写中断例程,将它们放到安装程序中,然后运行安装程序,将它们安装到指定的内存区中。此后,别的应用程序才可以调用。而BIOS和DOS提供的中断例程是如何安装到内存中的呢?我们下面讲解它们的安装过程。

(1) 开机后, CPU一加电, 初始化(CS) =0FFFFH, (IP) =0,自动从FFFF:0单元开始执行程序。FFFF:0处有一条转跳指令, CPU执行该指令后, 转去执行BIOS中的硬件系统检测和初始化程序。

(2)初始化程序将建立BIOS所支持的中断向量, 即将BIOS提供的中断例程的入口地址登记在中断向量表中。注意, 对于BIOS所提供的中断例程, 只需将入口地址登记在中断向量表中即可, 因为它们是固化到ROM中的程序, 一直在内存中存在。

(3)硬件系统检测和初始化完成后, 调用int 19h进行操作系统的引导。从此将计算机交由操作系统控制。

(4) DOS启动后, 除完成其他工作外, 还将它所提供的中断例程装入内存, 并建立相应的中断向量。

BIOS中断例程应用

下面我们举几个例子, 来看一下BIOS中断例程的应用。

int 10h中断例程是BIOS提供的中断例程, 其中包含了多个和屏幕输出相关的子程序。

一般来说,一个供程序员调用的中断例程中往往包括多个子程序,中断例程内部用传递进来的参数来决定执行哪一个子程序。BIOS和DOS提供的中断例程, 都用ah来传递内部子程序的编号

下面看一下int 10h中断例程的设置光标位置功能

(ah)=2表示调用第10h号中断例程的2号子程序,功能为设置光标位置,可以提供光标所在的行号(80*25字符模式下:0~24)、列号(80*25字符模式下:0~79),和页号作为参数。

bh中页号的含义:内存地址空间中, B8000H~B FFFFH共32kB的空间, 为80*25彩色字符模式的显示缓冲区。一屏的内容在显示缓冲区中共占4000个字节。

显示缓冲区分为8页,每页4KB(~4000B),显示器可以显示任意一页的内容。一般情况下,显示第0页的内容。也就是说,通常情况下,B8000H~B8F9FH中的4000个字节的内容将出现在显示器上。

再看一下int10h中断例程的在光标位置显示字符功能

(ah)=9表示调用第10h号中断例程的9号子程序,功能为在光标位置显示字符,可以提供要显示的字符、颜色属性、页号、字符重复个数作为参数。

bl中的颜色属性的格式如下。

编程:在屏幕的5行12列显示3个红底高亮闪烁绿色的'a'。

注意,闪烁的效果必须在全屏DOS方式下才能看到。

DOS中断例程应用

int 21h中断例程是DOS提供的中断例程, 其中包含了DOS提供给程序员在编程时调用的子程序。

我们前面一直使用的是int 21h中断例程的4ch号功能, 即程序返回功能, 如下:

mov ah,4ch ;程序返回

mov al,0 ;返回值

int 21h

(ah)=4ch表示调用第21h号中断例程的4ch号子程序,功能为程序返回,可以提供返回值作为参数。我们前面使用这个功能的时候经常写做:

mov ax,4c00h

int 21h

我们看一下int 21h中断例程在光标位置显示字符串的功能

ds:dx ;指向字符串,要显示的字符串需用"$"作为结束符

mov ah,9;功能号9,表示在光标位置显示字符串

int 21h

(ah)=9表示调用第21h号中断例程的9号子程序,功能为在光标位置显示字符串,可以提供要显示字符串的地址作为参数。

上述程序在屏幕的5行12列显示字符串"Welcome to masm!", 直到遇见""(""本身并不显示,只起到边界的作用)。

如果字符串比较长,遇到行尾,程序会自动转到下一行开头处继续显示;如果到了最后一行,还能自动上卷一行。

实验:

相关推荐
我在人间贩卖青春3 天前
汇编之伪指令
汇编·伪指令
我在人间贩卖青春3 天前
汇编之伪操作
汇编·伪操作
济6173 天前
FreeRTOS基础--堆栈概念与汇编指令实战解析
汇编·嵌入式·freertos
myloveasuka3 天前
汇编TEST指令
汇编
我在人间贩卖青春3 天前
汇编编程驱动LED
汇编·点亮led
我在人间贩卖青春3 天前
汇编和C编程相互调用
汇编·混合编程
myloveasuka4 天前
寻址方式笔记
汇编·笔记·计算机组成原理
请输入蚊子4 天前
《操作系统真象还原》 第六章 完善内核
linux·汇编·操作系统·bochs·操作系统真像还原
myloveasuka4 天前
指令格式举例
汇编·笔记·计算机组成原理
我在人间贩卖青春5 天前
汇编之分支跳转指令
汇编·arm·分支跳转