第五篇 直接面临系统资源的0号中断处理
学习汇编的一个重要目的就是获得面对底层编程的经验。
这也就是说有的时候我们这些编程者应该绕开操作系统,直接面向硬件要资源。当然,这
在某种程度上是不安全的。但请别忘了,我们在写汇编。
一、简单介绍下博文的目标
这篇博文主要是改写0号中断(除法溢出)的入口地址,使之执行编程者自己编写的中断处理
程序。系统提供的0号中断服务程序做法是打印divide overflow!,然后返回。新的中断服务
程序的目标是在屏幕中央打印overflow!,然后返回。
那么,怎么怎样体现直接向硬件要资源呢?举个例子,我们知道普通的子程序实在编译的时候
由系统分配一个安全的内存空间存储之。我写的新的中断程序则不这样了,分析程序可以发现,
我是直接将新的中断服务程序,拷到了内存0000:0200开始的空间。
到这里,细心的读者可能就会有两个疑问了。
1、我们虽然强调直接面向系统资源(这里主要是内存)编程,但我们总不能什么也不管什么也
不顾吧,本着破坏的目的吧?
2、为什么将中断服务程序写到内存0000:0200开始的区域呢?
回答这两个问题之前我们先来看看利用debug的D命令,查看内存0000:0200开始的256个字节的
内容。
到这里,上述的两个问题都可以迎刃而解了。从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
三、结果截图
四、代码中提到了两种打印overflow!方法。
1、DOS的功能调用-int 21h,利用其中的9号功能即可打印。其中,要将要打印的内容的首地址放到
ds:dx中,并且要打印的字符串要以$结尾。
2、直接要显存空间写数据,写入的数据会显示在屏幕上。
注:如果对显存不了解的可以到这里查看显存介绍及编程