汇编语言第十三章-int中断

本博文系列参考自<<汇编语言>>第三版,作者:王爽

本博文将继续介绍另外一种内中断类型,int中断。

13.1 int中断

int指令格式为:int n,其中n为中断类型码。

int n中断过程如下:

取中断类型码n

标志寄存器入栈,TF=0,IF=0

CS,IP入栈

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

上面的代码段运行后将在屏幕中间显示一个’!’,然后再显示一个”divide overflow”,这里符号”!”的显示是我们通过编程实现的。而字符串“divide overflow”则是通过int 0指令执行第0号中断处理程序,而系统设置的第0号中断处理程序则是显示字符串“divide overflow”。显示之后再回到dos系统。

可见int指令与call指令类型,都是调用一段程序。

后面我们将中断处理程序称为中断例程。

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

问题:编写,安装7CH的中断例程

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

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

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

举例:2*3456^2

分析一下,我们主要要做三部分的工作:

编写程序,实现求平方的功能

安装程序,将其安装在0200处

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

安装程序如下:

assume cs:code
code segment
start : mov ax,cs
mov ds,ax
mov si,offset sqr
mov ax,0
mov es,ax
mov di,200h
mov cx,offset sqrend-offset sqr
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在执行7ch例程之前,标志寄存器,CS与IP入栈,在执行完中断例程后,用iret来恢复CS和IP以及标志寄存器。从而接着执行应用程序。

call指令与ret指令配合使用同int指令与iret指令配合使用方式类似。

13.3对int、iret和栈的深入理解

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

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

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

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

分析:为了模拟loop指令,7ch中断例程应具有如下功能。

dec cx

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

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

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

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

Int 7ch进入中断例程,在中断过程中会将CS和IP压栈,此时CS和IP的内容为调用程序的段地址和int 7ch后一条指令的偏移地址。

现在知道如何从栈中间接的获取CS和IP,那么如何用它们来设置CS:IP呢?

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

7ch的中断例程如下:

	lp:push bp
	    mov bp,sp
	    dec cx
	    jcxz lpret
	    add [bp+2],bx
     lpret:pop bp
           iret

因为要访问栈,使用了bp,在程序开始处将bp入栈保存,结束时出栈恢复。当要修改栈中se的偏移地址的时候,栈的情况为:栈顶为bp原来的值,下面是se的偏移地址,再下面是s的段地址,再下面是标志寄存器的值。而此时,bp中为栈顶的偏移地址,所以((ss)*16+(bp)+2)处为se的偏移地址,将它加上bx中的转移位移就变成s的偏移地址。最后用iret出栈返回,CS:IP即从标号处开始执行。

如果(cx)=0,则不需要修改栈中se的偏移地址,直接返回即可。CPU从标号se处向下开始执行。

13.4  BIOS和DOS所提供的中断例程

在电脑主板的ROM中有一套程序,称为BIOS,BIOS主要包含以下几个部分:

硬件系统的检测和初始化程序;

外部中断和内部中断的中断例程

用于对硬件设备进行I/O操作的中断例程

其他和硬件系统相关的中断例程

操作系统DOS也提供了中断例程,从操作系统的角度看,DOS中断例程就是操作系统向程序员提供编程资源。

BIOS和DOS所提供的中断例程包含了很多子程序,这些子程序实现了程序员在编程的时候经常用到的功能。程序员在编程的时候,可以用Int指令调用bios或者dos提供的中断例程。

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

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

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

(3) 硬件检测和初始化完成后,执行int 19h进行系统引导,将计算机交给操作系统控制

(4)DOS启动后将其提供的中断例程装入内存,并建议相应的中断向量。

13.6  BIOS中断例程应用

Int 10h中断向量是BIOS提供的中断例程,其中包含多个和屏幕输出相关的子程序。一般来说中断例程用传入的参数来区别到底调用哪个子程序,BIOS和DOS提供的中断例程,都用ah来传递内部子程序的编号。

下面是int 10h中断例程设置光标位置:

(ah)=2表示调用10h中断例程的二号子程序,设置光标位置。

(bh)=0,(dh)=5,(dl)=12 设置光标第0页,第5行,第12列

bh中页号的含义:内存地址空间中,B8000H~BFFFFH共32kb的空间,为80*25彩色字符模式的显示缓冲区,一屏的内容在缓冲区为4000字节。显示缓冲区为8页,每页大概4kb,一般情况显示第0页。

13.7  DOS中断例程应用

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

前面我们经常使用

Mov ax,4c00h
Int 21h

(ah)=4ch表示调用21h中断例程的4ch号功能,(al)=00h为返回值。

再比如:使用21h中断例程在光标处显示字符:

ds:dx 指向字符串
mov ah,9
int 21h

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

时间: 2024-08-27 01:17:01

汇编语言第十三章-int中断的相关文章

《汇编语言 基于x86处理器》第十三章高级语言接口部分的代码 part 1

? 书中第十三章的程序,主要讲了汇编语言和 C/++ 相互调用的方法 ● 代码,数组求和的几种优化 1 int arraySum(int array[], int count) ; O0 2 { 3 010716D0 push ebp 4 010716D1 mov ebp,esp 5 010716D3 sub esp,0D8h 6 010716D9 push ebx 7 010716DA push esi 8 010716DB push edi 9 010716DC lea edi,[ebp-0

汇编入门学习笔记 (十三)—— 外中断

疯狂的暑假学习之  汇编入门学习笔记 (十三)--  外中断 参考: <汇编语言> 王爽 第15章 1.外中断信息 外中断分为可屏蔽中断和不可屏蔽中断 可屏蔽中断 先看看内中断所引发的中断过程: (1)取中断类型吗n. (2)标志寄存器入栈,设置IF=0,TF=0. (3)CS.IP入栈 (4)(IP)=(n*4),(CS)=(n*4+2) 可屏蔽中断的中断过程于内中断所引发的中断过程不同的地方只是,第一步不同.可屏蔽中断的中断过程,CPU要先看IF的值,如果IF=0就不执行中断,如果IF=1

c++第十三章 -(副本构造器)

逐位复制(bitwise copy):编译器将生成必要的代码把“源”对象各属性的值分别赋值给“目标”对象的对应成员的行为.对对象的地址赋值操作,于是乎,当删除一个对象时,它包含的指针也将被删除,但万一此时另一个副本(对象)还在引用这个指针,就会出问题! 要是程序员在当初进行对象“复制”时能够精确地表明应该复制些什么和如何赋值,那就理想了.为解决该问题,我们可以对=操作符进行重载,其中对指针进行处理:MyClass &operator= (const MyClass &rhs);该语句的意思

java-第十三章-类的无参方法(一)-查找客户姓名

package 上机练习; public class A02class { String names[] = new String[30]; public void showA(String name) { for (int i = 0; i < names.length; i++) { if (names[i] == null) { names[i] = name; break; } } } public void showB() { System.out.println("\t客户列表

java-第十三章-类的无参方法(一)-实现图形生成器

package 上机练习; public class A03class { public String showA(int rows, String ch) { for (int i = 0; i < rows; i++) { for (int j = 0; j <= i; j++) { System.out.print(ch); } System.out.println(); } return ch; } } package 上机练习; import java.util.Scanner; p

java-第十三章-类的无参方法(一)-模拟账户查询,实现存取款

package 上机练习; import java.util.Scanner; public class A04class { double Money = 0; public double showA() { return Money; } public void showB(double money) { Money += money; System.out.println("当前余额:" + Money); } public void showC(double money2) {

java-第十三章-类的无参方法(一)-代参方法的编程计算器

package 本章总结; public class A01class { public int ope(int Operator, int num1, int num2) { switch (Operator) { case 1: num1 += num2; break; case 2: num1 -= num2; break; case 3: num1 *= num2; break; case 4: num1 /= num2; break; default: System.out.print

java-第十三章-类的无参方法(一)-模拟一个简单的购房商贷月供计算器

package 本章总结; public class A02class { double Money = 0; public double showA(double money, int choice) { switch (choice) { case 1: Money = (money + money * 0.0603) / 36; break; case 2: Money = (money + money * 0.0612) / 60; break; case 3: Money = (mon

java-第十三章-类的无参方法(一)-根据三角形的三条边长,判断是直角,锐角还是钝角三角形

package 本章总结; public class A03class { public boolean showA(int a ,int b ,int c){ boolean con=false; if((a+b)>c&&(a+c)>b&&(c+b)>a){ con=true; } return con; } public String Shape(int a,int b,int c){ String shape=""; if((a=