Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1402329
  • 博文数量: 416
  • 博客积分: 13005
  • 博客等级: 上将
  • 技术积分: 3297
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-05 16:26
文章分类

全部博文(416)

文章存档

2014年(1)

2013年(4)

2012年(46)

2011年(64)

2010年(12)

2009年(4)

2008年(40)

2007年(187)

2006年(58)

分类:

2007-12-18 16:05:57

BIOS中断浅析
作者:lincon
  首先,我们介绍一下中断。中断大致可以分为四种类型:
  中断类型 中断号 处理器 0--4h
  硬件 8--F,70--77h
  软件 大部分为int形式,例外:
     1)1Dh,1Eh,46h返回在ROM中驻留的硬件参数表格
     2)20--3Fh用于DOS
     3)5,10--1A,1D--1F,40,41,43,46h用于BIOS
  用户 60--67,F1--FF 上表仅是一个粗略的说明,随着中断的发展,一些原先保留
的中断也有了确定的定义。现在所讲的BIOS中断意指中断0--1Fh。
  中断程序的执行过程简单说来,即中断程序在中断向量表中查到中断地址后,保存
现场,跳到中断地址执行程序,结束后再恢复现场继续执行中断前的程序。我们调用中
断就与调用一个c程序一样方便。
  BIOS固化于ROM中,是其他软件与硬件传递信息的桥梁。以应用的角度看,它的各个
中断程序是我们最感兴趣的。早在DOS时代,就有不少关于BIOS的介绍,那么到了Windo
ws纵横天下的时候,BIOS又有了什么变化和发展呢?下面我们将BIOS中断程序按编程的复
杂度由简单到复杂度选择进行分析。

  (一)准备工作
  一)开机后,BIOS中断程序驻留于内存F0000--FFFFF处,我们可先用DEBUG.EXE 将这
内存的内容复制成一个文件。例如:
  C:/>debug.exe
  -rbx
  BX 0000
  :1
  -n bios.dat
  -w f000:0
  Writing 10000 bytes
  -q
  然后,我们再将内存0:0 --0:700处的内容复制下来。此处主要有中断向量表,所
用到的BIOS数据区和DOS数据区。为了方便查看,以文本形式保存。例如:先编写一个批
处理文件C.bat,其内容为:
  @echo d 0:0 700 >temp
  @echo q>>temp
  type temp|debug.exe >bios.txt
  将C.bat执行后,得到一个bios.txt文件。
  二)熟悉DEBUG.EXE和PCTOOLS5.0 的用法。它们都是很老的软件了,但对付BIOS 还
是绰绰有余的(当然还有例外,下文将要讲到)。
  三)准备一本汇编方面的书籍。上面一般附有BIOS 中断。虽然不太全,但可以作为
参考。如清华大学计算机系教材《IBM-PC汇编语言程序设计》。
  四)那就是你必须具有相当熟练的汇编语言的知识,以及对硬件要有一定的了解,如
对8259A,8042 等计算机用到的硬件的端口要有比较清楚的认识,最少也得有一本这方
面的参考书,如我们就参考过《PC系列机系统开发与应用》,《微型计算机原理与汇编
语言》等十几本书籍。
  (二)纵览全局
  查看bios.txt ,地址0:0-0:700为中断0-1FH入口地址,如下图:
  0000:0000 9E 0F C9 00 65 04 70 00-16 00 A4 08 65 04 70 00 ....e.p.....e.
p.
  0000:0010 65 04 70 00 54 FF 00 F0-E2 47 00 F0 C8 E6 00 F0 e.p.T....G....
..
  0000:0020 00 00 00 CC 28 00 A4 08-6F EF 00 F0 6F EF 00 F0 ....(...o...o.
..
  0000:0030 6F EF 00 F0 6F EF 00 F0-9A 00 A4 08 65 04 70 00 o...o.......e.
p.
  0000:0040 05 00 75 CC 4D F8 00 F0-41 F8 00 F0 E7 25 53 FD ..u.M...A....%
S.
  0000:0050 39 E7 00 F0 40 02 13 02-2D 04 70 00 28 0A 5C 02 9...@...-.p.(.
\.
  0000:0060 A4 E7 00 F0 2F 00 65 09-6E FE 00 F0 04 06 5C 02 ..../.e.n.....
\.
  0000:0070 1D 00 00 CC A4 F0 00 F0-22 05 00 00 19 4E 00 C0 ........"....N
..
  但其中有些地址已经被DOS 修改了。我们可打开bios.dat 查看原来的地址,用PCT
OOLS 打开bios.dat,按F2 ,键入127 ,在相对扇区 127 处,偏移E3-122 的地方查到
原来的地址。我们以大众MVP3主板(VP3-586B-WB77)上的 AWARD BIOS(日期:98年7月2
0日)(注:以下都将以此BIOS为例)为例看一看,如下图:
  F000:FEE0 00 0F AA C8 E6 C8 E6 C3-E2 C8 E6 C8 E6 54 FF E2 .............T
..
  F000:FEF0 47 C8 E6 A5 FE 87 E9 6F-EF 6F EF 6F EF 6F EF 57 G......o.o.o.o
.W
  F000:FF00 EF 6F EF 65 F0 4D F8 41-F8 59 EC 39 E7 59 F8 2E .o.e.M.A.Y.9.Y
..
  F000:FF10 E8 D2 EF A4 E7 F2 E6 6E-FE 53 FF 53 FF A4 F0 C7 .......n.S.S..
..
  F000:FF20 EF 00 00 5E BB F3 EC 6F-EF 6F EF 6F EF FC F0 6F ...^...o.o.o..
.o
  可以看到,确实与0:700处的地址有差别。在127 扇区的结尾处,可看到BIOS 的日
期及机子型号,如:
  F000:FFF0 CD 19 E0 00 F0 30 37 2F-32 30 2F 39 38 00 FC AA .....07/20/98.
..
  如果你用PCTOOLS 查看各扇区,还可发现一些在CMOS SETUP设置时遇到的提示信息
,如:
  F000:0660 00 07 02 16 0B 39 0F 02-05 19 0D 53 41 56 45 20 .....9.....SAV
E
  F000:0670 74 6F 20 43 4D 4F 53 20-61 6E 64 20 45 58 49 54 to CMOS and EX
IT
  F000:0680 20 28 59 2F 4E 29 3F 20-00 07 02 16 0B 39 0F 02 (Y/N)? .....9.
.
  F000:0690 05 1A 0D 51 75 69 74 20-57 69 74 68 6F 75 74 20 ...Quit Withou
t
  F000:06A0 53 61 76 69 6E 67 20 28-59 2F 4E 29 3F 20 00 07 Saving (Y/N)?
..
  (三)最简单的中断程序
  为了提高自信心,我们先来看一看最简单的中断程序是怎样的。
  INT 1B,1CH为提供给用户的软中断,即用户如果不对它们进行修改,则它们是仅有
一条IRET指令的程序。
  INT 12H功能为检查基本内存容量。程序为
  PUSH DS
  MOV AX,40
  MOV DS,AX
  MOV AX,[13]
  POP DS
  IRET
  查看地址0:413H的内容,为280H,即十进制的640K,这说明基本内存为640K。 
  INT 0,1,3,4,7H 程序为:
  E6C8:PUSH DS
  PUSH AX
  PUAH CX
  MOV AX,40
  MOV DS,AX
  JMP EFBD
  EFBD:MOV AH,FF
  MOV [6B],AH
  POP CX
  POP AX
  POP DS
  IRET
  程序仅仅在地址0:46B处填入FF字节。我们知道,单步与断点两中断由DEBUG.EXE接
管和修改的,而其他则由DOS接管。故现在查看一下0:46B,已经不是FF了。
  INT 11H的程序为:
  JMP EE81
  EE81:PUSH DS
  MOV AX,40
  MOV DS,AX
  XOR EAX,EAX
  MOV AX,[10]
  POP DS
  IRET
  其中地址0:410H字为设备安装标志,意义为
  低字节:7,6位:软驱数量(00:1台;01:2台;10:3台;11:4台)
  5,4位:显示模式(01:40*25彩色;10:80*25彩色;11:80*25单色;00:上述以
外)
  3,2位:无意义
  1位:安装协处理器为1
  0位:安装软驱为1
  高字节:15,14位:并行口打印机数
  13位:无意义
  13位:安装游戏适配器为1
  11-9位:串行口数
  8位:保留
  显然,这些中断并没有做很多工作。你是不是没想过BIOS程序也有如此简单呢:
  (四)比较简单的中断程序
  在这一节,我们将介绍INT 5H以及INT 8H。
  INT 5H为打印屏幕中断,其编程思路很简单。程序先做好一些初始化工作,如检查
屏幕打印状态 ,以及通过INT 17H 检查打印机是否忙碌或纸尽。处理好以上过程后,就
开始打印了。打印调用了INT 17H,每调用一次打印一个字符。程序设计了一个二重循环
,内循环判断是否换行,外循环判断是否打印结束。就与一对FOR语句嵌套一样。
  总的说来,这个程序并无多少可看之处。不过,我们认为程序中开,关中断指令设
置的巧极了,它们的位置恰好保护了应该不被中断执行的程序段,具有一些"互斥"意味
。此外,打印时还对一些特殊字符进行了过滤,以空格代之打印。
  下面,介绍一下INT 8H--定时器中断程序。这里,我们感兴趣的是程序中涉及到了
时间。那么,它又是如何解决"千年虫"的问题的?原来,程序设置了一个子过程,它将年
代的高两位取出,判断是否为"19XX ",如果不是,则可认为是"20XX"年了;如果是,又
取出年代的高两位,判断是否小于"80",如小于,认为到了2000 年,则将年代的高两位
标志改为"20",如大于或等于,则认为仍在20世纪。
  此外,该程序中还对CMOS 的70,71 端口进行了操作,操作中使用了两条相邻的跳
转指令JCXZ进行延时,以确保对端口的操作准确无误。程序的末尾,对8259A主片的20
端口进行了操作。指令为
  MOV AL,20
  OUT 20,AL
  当用8259A来实现中断服务程序结束时(返回指令IRET 前),必须给8259A 送一条EO
I命令(即AL第五位为 1)。8259A收到这条命令后,将中断服务寄存器ISR中的相应位清零
,然后才可为其他同优先级的中断源服务。
  这个中断程序,完成了两个基本功能:计时和管理软磁盘驱动器的启动时间。每调用
一次此中断,时间就增加"一秒"(实际约为55毫秒),当小时标志为18H时,还要判断"秒
"标志是否到了B0H,这是为了弥补其计时方法引起的误差所采取的措施。程序在修改“
计时器”后,还调用了INT 1CH ,紧接着又调用了两个仅包含一条IRET指令的子过程。
这有什么作用呢?似乎给我们提供了修改此中断的好方法。
  总之,INT 8H是一个比较有意思的中断。由于程序不长,仅70 余行,有兴趣的读者
不妨将之反编译,完整的读一下。
  (五)INT 18H --一个暗伏圈套的中断
  当我们对BIOS进行反编译的时候,常常会碰到诸如DB 0F,DB 66等的语句,那么,
程序中出现这些语句又是什么意思呢?先前我们并没有很在意这些语句,仅仅简单的认
为它们是在修改BIOS中留下的无用语句(这可是一个可怕的错误)。然而,事实告诉我们
,这里隐藏着一个小秘密。让我们先来看一看这个程序。
  程序首先设置了屏幕显示格式,然后调用了子过程(CALL EDA8)一次。如果我们以
U F000:EDA8翻译它们,则会显示如下语句。
  EDA8:PUSH CX
  PUSH BX
  PUSH DS
  PUSH CS
  POP DS;DS=F000
  XCHG BX,BX
  NOP
  EDB0:LODSB ;DS:SI=“PRESS A KEY TO REROOT ”,0D 0A 00...
  OR AL,AL
  EDB3:DB 0F
  TEST AL,[DI]
  ADD AH,CH
  XOR AX,EB00
  HLT
  EDBC:POP DS
  POP BX
  POP CX
  RET
  而主程序为:
  E7A4:MOV AX,40
  MOV DS,AX
  XOR AH,AH
  MOV AL,[49]
  INT 10
  MOV SI,EA70
  CALL EDA8 ;显示“PRESS A KEY TO REBOOT”
  XOR AH,AH
  INT 16 ;等待按下任一键
  MOV WORD PTR [72],1234;跳过存储器测试
  JMP F470;跳向自检
  如果你试读一下,会发现简直莫名其妙,子过程没法读懂。问题出在那呢?我们曾
经为此费劲脑筋,直到有一次,我们尝试着运行这个程序,才发现运行的过程与表面的
显示有所不同。最终的结论是,DEBUG给我们开了一个大玩笑----DEBUG不认得这是一条
高级指令!!!子过程EDB0处的DB 0F开始之处为一条高级指令。大家可以参阅INTEL奔
腾机的用户参考手册,它其实是JZ指令。真实的子过程为:
  EDA8:PUSH CX
  PUSH BX
  PUSH DS
  PUSH CS
  POP DS
  XCHG BX,BX
  NOP
  EDB0:LODSB
  OR AL,AL
  JZ EDBC
  CALL EDEF
  JMP EDB0
  EDEF:PUSH AX
  PUSH BX
  MOV AH,0E
  MOV BX,3 ;背景为黑色
  INT 10 ;显示当前字符
  POP BX
  POP AX
  RET
  由于进行了JZ判断,所以程序进行了一个循环,从而显示了一个提示重新启动的字符
串--PRESS A KEY TO REBOOT。当然,如果你在WINDOWS下运行这个程序,将会得到一个
“程序异常结束”的警告,你可以将WINDOWS切换到MS_DOS模式下,执行这个程序将会重
启计算机。大家可以验证一下。
  我们从这个程序得到什么启示呢?
  1.不要被表面的现象所迷惑,不要想当然。
  2.要有扎实的基础知识,只有这样才能发现错误,改正错误。
  3.要多实践,不可死背书本。
摘自电脑报
阅读(4638) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~