汇编语言随笔(11)- int 指令(返回到应用程序的中断例程),实验13(编写、应用中断例程)

int 指令

      int 指令的格式为:int n,n为中断类型码。这里由 n 显式的给出了调用哪一个中断处理程序。
      CPU 的中断过程仍然是:
(1)取中断类型码n
(2)标志寄存器入栈,IF=0,TF=0
(3)CS、IP入栈
(4)(IP)=(nx4),(CS)=(nx4+2)
      比如:当除法溢出时产生的0号中断,会在屏幕上显示“Divide overflow”。我们也可以通过 int 0 指令来让屏幕上显示“Divide overflow”,虽然此时并没有发生除法溢出。

       当编写返回到应用程序的中断处理程序时,它与返回到dos系统的中断例程差别在于,它使用了iret指令来返回到应用程序,后者是通过 mov ax 4c00h        int 21h来返回的。
      iret指令的功能为IP 出栈,CS 出栈,标志寄存器出栈。它常和 int 指令来配合使用 ,就像 call 和 ret 指令一样。

      编写程序实现:在屏幕中间显示80个 '!’。要求用 int 指令来代替 loop 指令,其中需要将循环次数和指令转移位移做为参数。将循环次数放在 cx 中,位移放在 bx 中,完整程序如下:

	assume cs:code
	code segment
 start: mov ax,0b800h
		mov es,ax
		mov di,160*12
		
		mov bx,offset s-offset se		;设置标号s到se的转移位移
		mov cx,80						;循环次数
	 s: mov byte ptr es:[di],'!'
	 	add di,2
	 	int 7ch
	se: nop
	
		mov ax,4c00h
		int 21h
	code ends
	end start
		

      7ch 中断例程如下:

	 lp: push bp
	 	 mov bp,sp
	 	 dec cx				
	 	 jcxz lpend			;判断cx是否为0
	 	 add [bp+2],bx		;用转移位移bx更改IP的值
	 	 
  lpend: pop bp
		 iret

      采用 bp 来作为临时寄存器,需要对它进行入栈保存,结束时恢复。当要用 bx 来修改原来的应用程序偏移地址 IP 时,栈中的情况为:sp 指向 bp 的值,sp+2 指向原来的 IP,sp+4 指向原来的 CS,sp+6 指向原来的标志寄存器。原来程序的段地址 CS 和标号 s 的段地址 CS 是相同,故只需要改变原 IP 的值即可,通过 add [bp+2],bx 来改变。
      loop 指令是8位短转移指令,用来替代它的 int 指令是16位的近转移指令,这是需要注意的。

DOS和BIOS中断例程

      一般来说,一个供程序员调用的中断例程往往包括多个子程序,中断例程内用传递进来的参数来决定执行哪一个子程序。BIOS和DOS中的参数往往采用 ah 来传递。
      int 10h 是BIOS提供的中断例程,其中包含多个和屏幕输出相关的子程序。
      int 21h 是DOS提供的中断例程。我们一直使用的是 int 21h 中断例程的 4ch 号子程序,功能为程序返回,可以提供返回值作为参数。如下:

			mov ah,4ch			;4c作为参数进行程序返回功能
			mov al,0			;0作为返回值
			int 21h

      也可以像我们经常使用的那样:

 			mov ax,4c00h
 			int 21

实验13

      (1)编写安装 int 7ch 中断例程,功能为显示一个用0结束的字符串,中断例程安装在 0:200 处。
      参数:(dh)=行号,(dl)=列号,(cl)=颜色,ds:si指向字符串首地址。
      程序举例如下:

		assume cs:code
		data segment
			db "welcome to masm!",0
		data ends
		code segment
	 start: mov dh,10
			mov dl,10
			mov cl,2
			mov ax,data 
			mov ds,ax
			mov si,0
			int 7ch
			mov ax,4c00h
			int 21h
		code ends
		end start

      7ch 中断例程安装如下:

		assume cs:code
		code segment
			   mov ax,cs			;中断处理程序安装在0:200处
			   mov ds,cs
			   mov si,offset s
			   mov ax,0
			   mov es,ax
			   mov di,200h
			   mov cx,offset send-offset s
			   cld
			   rep movsb

			   mov ax,0				;设置中断向量表
			   mov ds,ax
			   mov word ptr ds:[7c*4],200h
			   mov word ptr ds:[7c*4+2],0
			   mov ax,4c00h
			   int 21h
			   
			s: push si				;中断处理程序的实现
			   push es
			   push di
			   
			   mov ax,0b800h
			   mov es,ax
			   mov di,160*dh+2*dl
		   lp: mov al,[si]
		   	   cmp al,0
		   	   je ok
		   	   mov es:[di],al
		   	   mov es:[di+1],cl
		   	   add di,2
		   	   inc si
		   	   jmp short lp
		   ok: pop di
		   	   pop es
		   	   pop si
		   	   iret
		   	   
		 send: nop	 			;这条指令是不会执行的,因为它没有被传送过去
		 
		 code ends
		 end start  

      (2)略。

      (3)下面程序在屏幕的2,4,6,8行显示4句英文诗,补全程序如下:

		assume cs:code
		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,8

		start: mov ax,cs
			   mov ds,ax
			   mov bx,offset s
			   mov si,offset row
			   mov cx,4
		   ok: mov bh,0			;选择显示缓冲区第0页
		   	   mov dh,[si]		;dh中保存行号
		   	   mov dl,0			;dl中保存列号
		   	   mov ah,2			;调用int 10h的2号子程序:置光标
		   	   int 10h

			   mov dx,[bx]		;ds:dx为待显示字符串的首地址,以'$'作为结尾符
			   mov ah,9			;调用int 21h的9号子程序:显示字符串
			   int 21h
			   add bx,2
			   inc si
			   loop ok
			   mov ax 4c00h		;调用int 21h的4c号子程序:程序返回,返回值为0
			   int 21h
		code ends
		end start

おすすめ

転載: blog.csdn.net/Little_ant_/article/details/108511878