第五篇 直接面临系统资源的0号中断处理

第五篇 直接面向系统资源的0号中断处理

学习汇编的一个重要目的就是获得面对底层编程的经验。

这也就是说有的时候我们这些编程者应该绕开操作系统,直接面向硬件要资源。当然,这

在某种程度上是不安全的。但请别忘了,我们在写汇编。

 

一、简单介绍下博文的目标

这篇博文主要是改写0号中断(除法溢出)的入口地址,使之执行编程者自己编写的中断处理

程序。系统提供的0号中断服务程序做法是打印divide overflow!,然后返回。新的中断服务

程序的目标是在屏幕中央打印overflow!,然后返回。

那么,怎么怎样体现直接向硬件要资源呢?举个例子,我们知道普通的子程序实在编译的时候

由系统分配一个安全的内存空间存储之。我写的新的中断程序则不这样了,分析程序可以发现,

我是直接将新的中断服务程序,拷到了内存0000:0200开始的空间。

到这里,细心的读者可能就会有两个疑问了。

1、我们虽然强调直接面向系统资源(这里主要是内存)编程,但我们总不能什么也不管什么也

不顾吧,本着破坏的目的吧?

2、为什么将中断服务程序写到内存0000:0200开始的区域呢?

回答这两个问题之前我们先来看看利用debug的D命令,查看内存0000:0200开始的256个字节的

内容。

第五篇 直接面临系统资源的0号中断处理

到这里,上述的两个问题都可以迎刃而解了。从0000:0200开始的内存区域虽然是系统存放

中断向量表的区域,但显然,系统没有提供那么多的中断,这区域为空。另外,由于这段区

域啥也没有,我们向这里写东西也一般不会引起不安全的事。

 

二、代码

data segment
	hint db 'overflow!','$'
	addr dw ?,?
data ends

code segment
	assume cs:code,ds:data
start:
	mov ax,data
	mov ds,ax

	;将新中断服务程序直接复制到地址0000:0200,此处不再向操作系统申请内存
	mov cx,offset doend - offset dostart
	mov si,offset dostart
	mov ax,seg dostart
	mov ds,ax
	mov ax,0000h
	mov es,ax
	mov di,0200h
	cld
	rep movsb

	mov ax,0
	mov es,ax
	
	;保存原中断地址
	mov ax,es:[0*4]
	mov addr[0],ax
	mov ax,es:[0*4+2]
	mov addr[2],ax
	

	;写入新中断地址
	cli
	mov word ptr es:[0*4],0200h
	mov word ptr es:[0*4+2],0000h
	sti	

	;产生除法溢出0号中断
	mov ax,0ffffh
	mov bh,1
	div bh

	mov ah,4ch
	int 21h

dostart:
	;显示字符串overflow!
	mov ax,data
	mov ds,ax
	
	;以下注释的部分是调用DOS功能调用在屏幕上打印字符串
	;mov dx,offset hint
	;mov ah,9
	;int 21h

	;直接向显存b8000:bffff内写入内容,也可以在屏幕上显示
	mov si,offset hint
	mov ax,0b800h
	mov es,ax
	mov di,12*160+36*2   ;设置在屏幕中央显示
	mov cx,9
again:
	mov al,[si]
	mov es:[di],al
	inc si
	add di,2
	loop again
	
	
	;将原中断服务程序地址写回
	cli
	mov ax,0
	mov es,ax
	mov ax,addr
	mov es:[0*4],ax
	mov ax,addr[2]
	mov es:[0*4+2],ax
	sti
	
	;程序退出
	mov ah,4ch
	int 21h
doend:
	nop
	
code ends
	end start

 

三、结果截图

第五篇 直接面临系统资源的0号中断处理

 

四、代码中提到了两种打印overflow!方法。

1、DOS的功能调用-int 21h,利用其中的9号功能即可打印。其中,要将要打印的内容的首地址放到

ds:dx中,并且要打印的字符串要以$结尾。

2、直接要显存空间写数据,写入的数据会显示在屏幕上。

注:如果对显存不了解的可以到这里查看显存介绍及编程