第五篇 直接面向系统资源的0号中断处理
学习汇编的一个重要目的就是获得面对底层编程的经验。
这也就是说有的时候我们这些编程者应该绕开操作系统,直接面向硬件要资源。当然,这
在某种程度上是不安全的。但请别忘了,我们在写汇编。
一、简单介绍下博文的目标
这篇博文主要是改写0号中断(除法溢出)的入口地址,使之执行编程者自己编写的中断处理
程序。系统提供的0号中断服务程序做法是打印divide overflow!,然后返回。新的中断服务
程序的目标是在屏幕中央打印overflow!,然后返回。
那么,怎么怎样体现直接向硬件要资源呢?举个例子,我们知道普通的子程序实在编译的时候
由系统分配一个安全的内存空间存储之。我写的新的中断程序则不这样了,分析程序可以发现,
我是直接将新的中断服务程序,拷到了内存0000:0200开始的空间。
到这里,细心的读者可能就会有两个疑问了。
1、我们虽然强调直接面向系统资源(这里主要是内存)编程,但我们总不能什么也不管什么也
不顾吧,本着破坏的目的吧?
2、为什么将中断服务程序写到内存0000:0200开始的区域呢?
回答这两个问题之前我们先来看看利用debug的D命令,查看内存0000:0200开始的256个字节的
内容。

到这里,上述的两个问题都可以迎刃而解了。从0000:0200开始的内存区域虽然是系统存放
中断向量表的区域,但显然,系统没有提供那么多的中断,这区域为空。另外,由于这段区
域啥也没有,我们向这里写东西也一般不会引起不安全的事。
二、代码
data segmenthint db 'overflow!','$'addr dw ?,?data endscode segmentassume cs:code,ds:datastart:mov ax,datamov ds,ax;将新中断服务程序直接复制到地址0000:0200,此处不再向操作系统申请内存mov cx,offset doend - offset dostartmov si,offset dostartmov ax,seg dostartmov ds,axmov ax,0000hmov es,axmov di,0200hcldrep movsbmov ax,0mov es,ax;保存原中断地址mov ax,es:[0*4]mov addr[0],axmov ax,es:[0*4+2]mov addr[2],ax;写入新中断地址climov word ptr es:[0*4],0200hmov word ptr es:[0*4+2],0000hsti;产生除法溢出0号中断mov ax,0ffffhmov bh,1div bhmov ah,4chint 21hdostart:;显示字符串overflow!mov ax,datamov ds,ax;以下注释的部分是调用DOS功能调用在屏幕上打印字符串;mov dx,offset hint;mov ah,9;int 21h;直接向显存b8000:bffff内写入内容,也可以在屏幕上显示mov si,offset hintmov ax,0b800hmov es,axmov di,12*160+36*2 ;设置在屏幕中央显示mov cx,9again:mov al,[si]mov es:[di],alinc siadd di,2loop again;将原中断服务程序地址写回climov ax,0mov es,axmov ax,addrmov es:[0*4],axmov ax,addr[2]mov es:[0*4+2],axsti;程序退出mov ah,4chint 21hdoend:nopcode endsend start
三、结果截图

四、代码中提到了两种打印overflow!方法。
1、DOS的功能调用-int 21h,利用其中的9号功能即可打印。其中,要将要打印的内容的首地址放到
ds:dx中,并且要打印的字符串要以$结尾。
2、直接要显存空间写数据,写入的数据会显示在屏幕上。
注:如果对显存不了解的可以到这里查看显存介绍及编程