利用DOS/WINDOWS9X的隐含扇区保护数据
摘要:本文介绍如何利用视窗系统(WINDOWS)所不能管理的硬盘空间来达到特殊的数据保护要求,和如何编写MBR程序来完成特殊的系统服务
关键词:主引导记录(MBR),引导记录(DBR),CHS寻址,分区表
一、 引言
一谈到数据保护,大家就会想到用加密、磁盘阵列(数据备份系统)、硬盘保护卡等方法进行数据保护。不错,这些方法都很好,但对于普通个人用户来说是不实际的。而本文探讨另外一些可行的系统数据保护方法。
什么数据需要保护呢?一些你不想被别人知道的数据,如你的银行密码;一些你不想被别人盗取的数据,如你的论文;一些容易被破坏的数据,如公共机房的电脑中系统文件。
二、 DOS/WINDOWS9X不能管理的硬盘空间
现今,个人微机机的高速发展使得视窗操作系统无处不在。存储技术的发展也使得硬盘的容量不断增大。但视窗系统不能完全利用所有的硬盘空间,我不是说视窗系统不能支持这些大容量的硬盘,而是视窗系统无法利用这些硬盘空间----这就是所谓的隐含扇区。
硬盘上有几块的空间是视窗系统所不能读写的。众所周知,使用硬盘之前一定要分区,硬盘的0磁头0柱面1扇区保存了第一张分区表(主分区表),分区表所在的磁道(0磁头0柱面的第一个磁道63个扇区),和其他逻辑驱动器的分区表(分区链表)所在的磁道。而且一般硬盘用LBA模式管理硬盘空间,硬盘最后的两个柱面DOS/WIDOWS系统也没有使用。例如:2.1G的硬盘使用LBA模式有1023柱面、64个磁头/柱面和63个扇区/磁道,共1023柱面X64磁头/柱面X63扇区/磁道X512字节/扇区,若2014MB;而视窗系统的分区程序分出来的最后一个扇区的位置(也就是操作系统所管辖的硬盘空间)是255柱面,253磁头,63扇区(柱面和磁头是通过换算出来的逻辑数据),共(254柱面X255磁头/柱面+1柱面X253 磁头/柱面)X63扇区/磁道X512字节/扇区,若2000MB。很明显有14MB的空间没有用上,这是因为不同的硬盘寻址模式的转换而造成的部分空间不能使用(丢失)。
系统的INT 13H API允许程序读写这些视窗系统不能管理的空间,这些没用上的额外空间就可以用来保存一些秘密的信息,例如:某些软件的加密数据就保存在硬盘的0磁道。这些额外的空间上没有FAT,簇等概念,要读写这些空间,只有通过CHS寻址定位扇区,用13号中断进行扇区读写。当然,这需要有一定的编程能力和对硬盘有一定的了解!
三、MBR(MASTER BOOT RECORD)扇区
这些额外空间中最有魅力的是MBR扇区,这个扇区位于硬盘的0磁头0柱面1扇区。MBR扇区是系统启动时自检后INT 19H首先读取MBR扇区的512Bytes内容到内存0:7C00,然后把控制权交给MBR扇区。它的魅力就在与此,这时操作系统还没有加载,反而操作系统还需要MBR程序来引导,所以MBR扇区又叫主引导扇区,相对于视窗系统的引导记录叫DBR(DOS BOOT RECORD)。一些主引导扇区的病毒就利用了MBR扇区的特点,操作系统还没引导就执行了病毒代码,进行破坏!
这是一把双刃的剑,利用好了它同样能为大家提供优质的服务。最常见的例子就是多操作系统的引导。MBR扇区虽然只有512BYTES,这对于引导程序来说是足够的。但它所在的0磁道的其他扇区没有用上,视窗系统的分区表形成一个链表,有多少个逻辑驱动器就会有多少个分区表,也就是有相应多的磁道没有使用。在视窗系统下,不能对这些磁道直接读写。只有用程序读出分区链表,得到分区情况和这些磁道的地址,再用INT 13加以利用。例如,编写一个增强的主引导记录(MBR),但程序大小超过512Bytes,可以把程序的二进制代码分成多个512Bytes,分别存在0磁道上,但首先执行的代码必须放在MBR扇区里,而且要保留好主分区表(共64BYTES)和MAGIC ID(2Bytes);MBR执行时,MBR把程序的其他部分从0磁道读到内存里再执行。理论上,主引导程序只受隐含磁道的多少限制,一个磁道时31.5KBYTES,主引导程序和分区表必须保证不被破坏(防止某些软件运用隐含磁道,而破坏主引导记录),所以程序必须高效、精练和短小,最好用汇编语言编写。
还有一点,主引导程序必须保存在隐含扇区里,这是视窗系统的文件管理子系统所不能做到的。所以,必须用一个安装程序把主引导程序的程序代码和数据(MBR)当作安装程序的数据通过INT 13H的写扇区操作把MBR写到0磁道0扇区扇区里。这样的操作有一定的危险,因为原来的主引导记录和主分区表会被破坏,所以千万要备份原来的MBR和主分区表,并完全复制主分区表到新的主引导记录里。
四、利用硬盘额外空间
干才提到,用INT 13H 可以把数据写到硬盘的隐含磁道里。同样,也可以把数据读出来。怎样才能把一些想要藏起来的数据好好的藏起来?
其实,13号中断对硬盘的访问是以扇区为单位的,而扇区又以字节为最小的单位。事实上所有的数据都可以当作字节流看待,忽略其实际的数据结构,运用INT 13H的02H号读扇区子功能和03H号写扇区子功能,就可以轻易的从硬盘读写数据。至于13号中断的用法,很多汇编的书上都有介绍,这不是本文探讨的内容!
有一个问题,怎么知道硬盘上哪些地方操作系统没有用上?前面已介绍了视窗系统没有使用硬盘的大概哪一处,现在介绍怎么通过计算来得知具体的位置。先来介绍一些硬盘存储结构的知识。
一个硬盘设计时就有定好了硬件参数,有多少个物理磁头,物理柱面,每磁道有多少个扇区,BUFFER有多大等,必须清楚现今的硬盘是一个三维的立体结构(CHS--CYLINDER,HEAD,SECTOR)。硬盘在出厂时就已经进行低级格式化,每一个扇区都标明了寻找地址,标记了坏扇区,并给出实际容量。这时的硬盘就象一张有小格的纸,操作系统的分区程序把硬盘划分为多个区域,再用高级格式化程序格式化每个区域以便于文件系统进行文件存储。前面提及,硬盘分区表也保存再隐含磁道里,而分区表是一个链表结构,得知每所有的隐含磁道的位置。现在简要介绍一下分区表的结构:
硬盘分区表(Hard Disk Partition Table)是记录硬盘分区信息的数据。一般情况下,硬盘的0磁头0柱面1扇区(即MBR-Master Boot Record 扇区)保存了硬盘第一张分区表(主分区表),分区表位于该扇区位移1BEH处,连续40H个字节。一张分区表最多可以容纳四个分区表项,每个表项占用10H个字节,一个分区表项代表一个分区的使用情况。分区表项的数据结构适合INT 13H的数据格式。
分区表项的结构是这样的:第0字节80H是活动分区的标志,非活动分区为00H;第1,2,3字节表示分区的起始位置,第4字节为是操作系统标志,不同操作系统使用不同的标记;第5,6,7字节表示终止位置,第8,9,10,11字节表示以当前分区为基准相对于本分区首扇区相对号,第12,13,14,15字节指出分区占用扇区总数。起始地址和终止地址是用CHS的寻址方式,地址用3个字节表示,分区起始(结束)的柱面及扇区数据合用前两个字节,第一字节的低6位为分区起始扇区值,最大为63(扇区由1开始计数),高字节的高2位与低字节的8位共10位为分区起始柱面值,最大值为1023(第三字节是磁头号,最大值为255柱面和磁头由0开始计数)。视窗系统的分区链表结构,主分区表项是活动分区,扩展分区表项表示扩展分区的信息,扩展分区里有可划分逻辑分区(逻辑驱动器);扩展分区表项的第1、2、3字节指示第一个逻辑分区的分区表的位置;如果存在第二个逻辑分区,这个分区表的第二个表项的第1、2、3字节又指示下一个逻辑分区表的位置,如果没有这个表项为0值。这就形成了链表的结构。
在缺省的情况下,视窗系统的分区程序把每一张分区表保存在隐含磁道的首扇区,但一个磁道有63个扇区,就是说还有62个扇区共31KB没使用。至于怎样利用这些空间就要看需要了。通过读取分区链表,得到操作系统使用硬盘的情况,对比一下BIOS(基本输入输出系统)检测到的有关硬盘的信息(保存在CMOS数据中),就可以知道操作系统到底有多少空间没有用上(主要是硬盘最后一个柱面的部分扇区)。可以通过调用INT 13H的08H号子功能返回硬盘的最大柱面号。前面的计算额外硬盘空间的例子,就知道视窗系统有好几MB的空间不用!越大的硬盘额外硬盘空间就越大!
把一些秘密的敏感的数据保存在这些视窗系统遗弃的空间里,别人无法通过操作系统读取,至于放在哪里,以什么形式存放,只有你和你的程序知道,有一定的保密效用!
五、示范实例
有很多的文章介绍一些使用这些硬盘特殊空间的思想。例如,利用硬盘额外空间存放个人的机密文件,CMOS数据或个人软件的加密数据;写一个新的能把某一分区保护起来INT 13H服务程序保存在隐含磁道里,用一个特殊的MBR把新的INT 13H服务程序驻留内存,达到硬盘软保护卡的功能。
现在以一个CMOS数据自我保护的MBR程序的编写为例子,具体说明数据怎么保存在隐含扇区里和增强主引导记录的程序编写。CMOS数据的保护有多种方法,有人用VXD技术对CMOS数据进行写保护;有人用文件保存CMOS数据,在自动批处理文件中用程序把CMOS数据文件中的数据回写CMOS中,这同样达到保护的功效。
本文的例子的CMOS数据保护的原理是:首先,通过端口70H和71H把CMOS数据读取出来;然后,用INT 13H的03H子功能把CMOS数据写到一个隐含扇区中,例如:0柱面0磁头29扇区;再编写相应的MBR,在每次引导时把隐含扇区中的CMOS数据写回CMOS。这样也达到CMOS数据的保护功能!
这里涉及到CMOS数据的读写方法和MBR程序的编程技巧。不同公司出品的BIOS,它们的CMOS数据格式有所不同,但都时先把CMOS地址(一个CMOS地址读写一个字节的数据)送端口70H,再用端口71H读写这个CMOS地址的数据。AWARD公司出品的BIOS头10H字节保存一些动态的CMOS数据如时间,后70H字节保存一些硬件信息和用户配置设置,只须把后面70H个字节的比较固定的CMOS数据保存起来。
MBR--主引导记录,系统自检后由19号中断服务程序把MBR扇区中的数据,也就是MBR程序读到内存地址0:7C00H中,然后把控制权交给MBR。本文的MBR程序按以下流程完成CMOS数据回写和读取操作系统引导(DBR)记录到内存,并把控制权交给DBR进行操作系统引导。
1. 把MBR从内存0:7C00H搬移到内存0:0600H,共512Bytes;
2. 跳到从内存0:0600H到0:0700H中的MBR搬移代码后的位置继续执行,把保留CMOS数据隐含扇区读到内存0:0800H;
3. 设置CMOS的地址端口(70H)和读写端口(71H),把内存0:0800中的70H个CMOS数据回写CMOS中;
4. 依次读取主分区表的四个分区表项的的内容,判断是否为可引导分区,如果是转5,否则打印“Invalid partition table.”信息并进入死循环;如果四个分区表项都无效则进入Rom Basic;
5. 保存可引导分区表项的起始扇区地址,多次读取引导扇区(DBR)到内存0:7C00H,如果读取DBR成功并通过MACIC ID(魔数AA55)判断是否为引导记录,如果是控制权转移到0:7C00H,继续进行操作系统的引导,否则打印“Missing operating system.”信息并进入死循环;如果读取DBR不成功,打印“Error loading operating system.”信息并进入死循环;
(文后附汇编源程序并有编译方法和程序说明)
有了MBR,怎么把它写到MBR扇区里面呢?先把文后的程序编译成EXE文件,再用DEBUG把程序的代码和数据提取到一个文件里(方法程序中附有)。你可以用程序把这个512BYTES的文件读到内存字节数组中,再把数组用INT 13H写到0柱面0磁头1扇区中。又可以用程序把MBR文件的二进制数据转化成你所用编程语言可以接受的数据表示形式加到你的安装程序中,把这些数据写到硬盘中。安装程序用C语言或汇编语言写都可以,但MBR程序一定要用汇编语言写!文后也附有一个安装程序(CMBOOTLD.ASM)和数据转化程序(BINTODAT.C)。
同样,还可以想出更多更实用的想法来,如,加密分区表,设密码授权访问硬盘,用两个同样大小的分区模拟备份系统等。模拟备份系统在公共机房中快速恢复系统是比较实用的。利用现在大硬盘的优势,分出两个同样大小的分区A、B,在其中A分区中安装操作系统和应用软件,并编写一个管理程序把A分区的内容完整复制到B分区上,并隐藏B分区;写一个主引导记录,每次引导时可以用热键管理选择把B分区的内容恢复(复制)到A分区或正常启动。MBR能实现的功能还有很多,你可以充分发挥你的想象力去设计这样的MBR!
六、结束语
由上面的文字看来,充分使用硬盘的空间似乎很简单,但这需要对硬盘有比较深的了解,能自如运用C/C++或汇编语言。总的来说,有扎实的功底一切会更好。现在存储技术的高速发展,硬盘的容量和速度大大的提高,是否有需要象文中所述的那样想尽办法利用硬盘空间?其实答案是,你是否有一些特别的需要,而本文所述的方法能确切的解决你的问题!希望本文能给大家一些帮助。
参考文献
〈〈硬盘保护技术手册〉〉 人民邮电出版社 1996年三月版
〈〈计算机组织与设计:硬件/软件接口〉〉机械工业出版社
[附:]
1. 主引导记录源程序
; **********************************************************************
; * cmosboot.asm HardDisk Cmos data self reload boot Program *
; *====================================================================*
; * tasm cmosboot *
; * tlink cmosboot *
; * exe2bin cmosboot *
; * debug cmosboot.exe *
; * -n cmosboot.bin *
; * -rcx *
; * :200 *
; * -w cs:0 *
; * -q *
; * bintodat cmosboot.bin cmosboot.doc *
; * bintocat cmosboot.bin cmosboot.cat *
; * *
; **********************************************************************
; **********************************************************************
; * Designer:Howard *
; * Creat date:08/13/2000 *
; * Original place:Wuhan *
; * Modification date:09/13/2000 *
; * Now version: 1.0 *
; **********************************************************************
; **********************************************************************
; * Modification History *
; *====================================================================*
; * Version 1.0 1.This program is a Master Boot Record. *
; * 09/13/2000 2.It can reload cmos data to the cmos when boot the *
; * the machine from Hard Disk every time *
; * 3.The cmos data haved backuped to the Hard Disk *
; * 0 cylinder,0 head,29 sector. *
; * 4.Before install this MBR to the Hard Disk,The cmos *
; * data must be haved Backuped to the Hard Disk *
; * 5.The cmos data is only 20 bytes,it is from cmos *
; * data address 10h to 2Fh. *
; **********************************************************************
PartLoad equ 600h ;
TableBegin equ 7beh ;partition table address in the memory
BootLoc equ 7c00h ;dos boot sector loaded to the address
IDAddr equ 7dfeh ;dos boot sector ended flag(55aah)
.MODEL tiny
.CODE
org 0
Head:
start:
cli ;disable the interrupt (if=0)
xor ax,ax ;ax=0
mov ss,ax ;ss=ax
mov sp,7c00h ;sp=7c00h
mov si,sp ;si=sp
push ax
pop es ;es=0
push ax
pop ds ;ds=0
sti ;enable the interrupt (if=1)
cld ;disable the direction (df=0)
mov di,PartLoad ;di=600h
mov cx,100h ;cx=100h (512 bytes=256 words)
repne movsw ;move the Master Boot Record from 0:7c00 to 0:600
db 0eah ;0eah is far jump code,that is jmp far ptr contiune
dw offset Continue+600h,0000h ;jump to 0:continue+600h
; ************************************************************************
; * The continue code is read the cmos backup data from hard disk sector.*
; * And rewrite the data to cmos. *
; ************************************************************************
continue:
mov ax,0201h ;ah=02h,al=01h
mov bx,0800h ;bx=800h,cmos data read to 0:800h
mov cx,001dh ;ch=00h,cl=1dh (the No.29 sector)
mov dx,0080h ;dh=00h (the No.0 head),dl=80h (Hard Disk)
int 13h
mov ax,0010h ;al=10h cmos unit address
mov cx,0020h ;write 20h bytes cmos data to cmos
cld ;disable the direction df=0
writecmosdata:
out 70h,al ;set the cmos data address
push ax ;the address backup to stack
mov al,[bx] ;al=[bx]
out 71h,al ;write a byte data the address
pop ax
inc al ;the next address
inc bx ;the next byte data
loop writecmosdata ;loop
std ;enable the direction df=1
@next1:
mov si,TableBegin ;si=Partition table begin address
mov bl,4 ;4 sets partition data
FindBoot:
cmp byte ptr [si],80h ;Boot partition?
je SaveRec ;if yes then jump to SaveRec
cmp byte ptr [si],0 ;=0?
jne Invalid ;Invalid partition
add si,10h ;the next partition
dec bl ;bl-1
jnz FindBoot ;continue findboot
int 18h ;jump to rom basic
SaveRec:
mov dx,[si]
mov cx,[si+2] ;let Boot partition first sector to cx
mov bp,si ;bp=si
; ********************************
; * Checked the next partition *
; ********************************
FindNext:
add si,10h
dec bl
jz SetRead ;jump to setread
cmp byte ptr [si],0
je FindNext
Invalid:
mov si,offset ErrMsg1+600h ;Errmsg address to si
PrintMsg:
call PrintStr ;print the msg
DeadLock:
jmp short DeadLock ;Dead lock
SetRead:
mov di,5 ;set reading dos boot sector 5 times
; *******************************************************************
; * read the dos boot sector in order to boot the operating system *
; *******************************************************************
ReadBoot:
mov bx,BootLoc ;the dos boot sector read to 0:7c00
mov ax,201h ;ah=02h,al=01h
push di ;di pushed to stack(backup the reading times)
int 13h
pop di
jnc GoBoot ;if reading ok then boot the OS
xor ax,ax ;ax=00h
int 13h ;reset the driver
dec di ;di-1
jnz ReadBoot ;continue read boot sector
mov si,offset ErrMsg2+600h ;get errmsg2 address to si
jmp short PrintMsg ;print the msg
GoBoot:
mov si,offset ErrMsg3+600h ;get errmsg3 address to si
mov di,IDAddr ;di=boot sector last two bytes
cmp word ptr [di],0AA55h ;is a boot sector
jne PrintMsg ;if not boot sector then print errmsg
mov si,bp ;si point to bootable partition
db 0EAh,00h,7Ch,00h,00h ;jump to 0:7c00h
; **********************
; * Error message *
; **********************
ErrMsg1 db 'Invalid partition table.',0
ErrMsg2 db 'Error loading operating system.',0
ErrMsg3 db 'Missing operating system.',0
PrintStr:
lodsb ;read a byte from [si]
cmp al,0 ;al=0?
je @exit ;if yes the jump to @exit
push si ;push si to stack
mov bx,7 ;
mov ah,0Eh ;display the char
int 10h
pop si
jmp short PrintStr ;print the next char
@exit:
retn
Tail: ;the Master Boot Record tail
FillNum equ 1BEh-(Tail-Head) ;count the fill number
db FillNum dup (0)
; *******************************************************************
; * The Parttition table data *
; * Notise: You must change the next parttition table data to your *
; * own Hard Disk parttition table data. *
; *******************************************************************
parttable db 80h,01h,01h,00h,06h,3Fh,7Fh,96h,3Fh,00h
db 00h,00h,01h,0Ah,19h,00h,00h,00h,41h,97h,0Fh,3Fh
db 0FFh,0FDh,40h,0Ah,19h,00h,00h,0E6h,25h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h
MagicID dw 0AA55h
end start
2. 主引导记录的安装程序
; *********************************************************************
; * Program:The Cmboot.exe MBR Sector loader.And read the cmos data *
; * and saved it to the harddisk hidden sector. *
; *===================================================================*
; * tasm Cmbootld1.asm *
; * tlink Cmbootld *
; *===================================================================*
; * Designer:Howard *
; * Creat Date:08/29/2000 *
; * Original place:Wuhan *
; * Modification date:08/29/2000 *
; * Now Version:1.0 *
; *===================================================================*
; * Modification History *
; *-------------------------------------------------------------------*
; * Version:1.0 1.Backup the old mbr to a file. *
; * 08/29/2000 2.Load the backup mbr file and saved it to the mbr *
; * sector(cylinder:0,head:0,sector:1). *
; * 3.Saved the cmos data to hard disk hidden sector. *
; * 4.Load the cmoscheckedmbr the mbr sector. *
; * 5.Reboot the computer. *
; *-------------------------------------------------------------------*
; *08/30/2000 6.Modify the psp and _data segment mistake. *
; *-------------------------------------------------------------------*
; * 09/01/2000 7.Modify some bug,and optimize some instructions. *
; *-------------------------------------------------------------------*
; * 09/07/2000 8.Modify the parameter error,ignore the space bet- *
; * ween the program name and parameter. *
; * 9.Modify the file creating problem,add zero to the *
; * end of filename string. *
; *********************************************************************
; * problem: 1.The _data and psp segment address is still a problem. *
; * 09/01/2000 Use a debug information.Maybe the buffer offset address*
; * is not correct,or the data segment is too large. *
; * I haved used two mem unit to save the psp and _data *
; * segment address.Do not use the stack to save psp and *
; * data segment address. *
; * 2.The file "creat/open/read/write" operating is still *
; * a problem. *
; *-------------------------------------------------------------------*
; * bugs: 1.Int 13h ah=02/03h es:bx point to the buffer,but *
; * modifying program executing,es=psp segment address,it must *
; * 09/01/2000 be make it equarl the real buffer segment address. *
; * 2.Push and pop operating must be make sure the *
; * operands is correct. *
; * 09/07/2000 3.The program can not creat a new file.error writing *
; * device AUX. *
; *********************************************************************
; dosseg
.model small
.486
.stack 200h
.data
;以下数据(SECTOR)是通过编译CMOSBOOT.ASM后用DEBUG得到CMOSBOOT.bin和并用BINTODAT.EXE转换CMOSBOOT.BIN得出来的
sector db 0FAh,33h,0C0h,8Eh,0D0h,0BCh,00h,7Ch,8Bh,0F4h,50h,07h
db 50h,1Fh,0FBh,0FCh,0BFh,00h,06h,0B9h,00h,01h,0F2h,0A5h
db 0EAh,1Dh,06h,00h,00h,0B8h,01h,02h,0BBh,00h,08h,0B9h
db 1Dh,00h,0BAh,80h,00h,0CDh,13h,0B8h,10h,00h,0B9h,70h
db 00h,0FCh,0E6h,70h,50h,8Ah,07h,0E6h,71h,58h,0FEh,0C0h
db 43h,0E2h,0F3h,0FDh,0BEh,0BEh,07h,0B3h,04h,80h,3Ch,80h
db 74h,0Eh,80h,3Ch,00h,75h,1Ch,83h,0C6h,10h,0FEh,0CBh
db 75h,0EFh,0CDh,18h,8Bh,14h,8Bh,4Ch,02h,8Bh,0EEh,83h
db 0C6h,10h,0FEh,0CBh,74h,0Dh,80h,3Ch,00h,74h,0F4h,0BEh
db 0A1h,06h,0E8h,83h,00h,0EBh,0FEh,0BFh,05h,00h,0BBh,00h
db 7Ch,0B8h,01h,02h,57h,0CDh,13h,5Fh,73h,0Ch,33h,0C0h
db 0CDh,13h,4Fh,75h,0EDh,0BEh,0BAh,06h,0EBh,0E0h,0BEh,0DAh
db 06h,0BFh,0FEh,7Dh,81h,3Dh,55h,0AAh,75h,0D4h,8Bh,0F5h
db 0EAh,00h,7Ch,00h,00h,49h,6Eh,76h,61h,6Ch,69h,64h
db 20h,70h,61h,72h,74h,69h,74h,69h,6Fh,6Eh,20h,74h
db 61h,62h,6Ch,65h,2Eh,00h,45h,72h,72h,6Fh,72h,20h
db 6Ch,6Fh,61h,64h,69h,6Eh,67h,20h,6Fh,70h,65h,72h
db 61h,74h,69h,6Eh,67h,20h,73h,79h,73h,74h,65h,6Dh
db 2Eh,00h,4Dh,69h,73h,73h,69h,6Eh,67h,20h,6Fh,70h
db 65h,72h,61h,74h,69h,6Eh,67h,20h,73h,79h,73h,74h
db 65h,6Dh,2Eh,00h,0ACh,3Ch,00h,74h,0Bh,56h,0BBh,07h
db 00h,0B4h,0Eh,0CDh,10h,5Eh,0EBh,0F0h,0C3h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,80h,01h,01h,00h,06h,3Fh,7Fh,96h,3Fh,00h
db 00h,00h,01h,0Ah,19h,00h,00h,00h,41h,97h,0Fh,3Fh
db 0FFh,0FDh,40h,0Ah,19h,00h,00h,0E6h,25h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,55h,0AAh
res dw 0072h,0040h
dat dw 0000h,0ffffh
buffer db 512 dup(0)
filename db 'hdpt.dat',0
parameter db 2 dup(?)
copyright db 0dh,0ah,'JiangBiFang,I love you!','$'
helpmsg db 0dh,0ah,'1.cmbootld /c'
db 0dh,0ah,' Saved the cmos data to hard disk hidden sector.'
db 0dh,0ah,'2.cmbootld /w'
db 0dh,0ah,' Load the old mbr data from a file and saved it to mbr sector.'
db 0dh,0ah,'3.cmbootld /s'
db 0dh,0ah,' Saved the mbr sector to a file.'
db 0dh,0ah,'4.cmbootld /l'
db 0dh,0ah,' Load the cmoschecked mbr sector to hard disk.'
db 0dh,0ah,'5.cmbootld /r'
db 0dh,0ah,' Reboot the computer.'
db 0dh,0ah,'6.cmbootld /?'
db 0dh,0ah,' Print the help message.','$'
noparamsg db 0dh,0ah,'Please use cmbootld /? for help.','$'
; debug db 0dh,0ah,'Debug message.','$'
hdbkokmsg db 0dh,0ah,'Harddisk mbr back ok.','$'
hdreaderrmsg db 0dh,0ah,'Harddisk reading error!','$'
hdwriteerrmsg db 0dh,0ah,'Harddisk writing error!','$'
filecreaterrmsg db 0dh,0ah,'File creating error!','$'
fileopenerrmsg db 0dh,0ah,'File opening error!','$'
filewriteerrmsg db 0dh,0ah,'File writing error!','$'
filewriteokmsg db 0dh,0ah,'File writing OK!','$'
filereaderrmsg db 0dh,0ah,'File reading error!','$'
mbrwriteokmsg db 0dh,0ah,'The cmoschecked mbr loading ok!','$'
cmossavedtohdokmsg db 0dh,0ah,'The cmos data haved to harddisk.','$'
mbrbkokmsg db 0dh,0ah,'The old mbr haved backup to the file hdpt.dat.','$'
cmoscheckedmbrldokmsg db 0dh,0ah,'The cmoscheckedmbr haved installed ok!','$'
wrongparamsg db 0dh,0ah,'The wrong parameter:"','$'
.code
start:
main proc far
assume cs:_text,ds:_data,es:_data,ss:stack
mov cs:pspseg,ds
; push ds
xor ax,ax
mov ax,_data
mov cs:dataseg1,ax
mov ds,ax ;ds=_data
mov es,ax ;int 13h es:bx point to buffer,es=seg _data
lea dx,copyright
call disp1
; push ds
; pop cx ;cx=_data
; pop ds ;ds=psg
mov ds,cs:pspseg ;ds=psp
cld
mov si,81h
lodsb
; push ds
; mov ds,cx ;ds=_data seg
mov ds,cs:dataseg1 ;ds=_data
cmp al,0dh
jz nopara
cmp al,' '
jz judgespace
; pop ds ;ds=psp
continue:
push si
dec si
mov ds,cs:pspseg
lodsb
; push ds
; mov ds,cx ;ds=_data
mov ds,cs:dataseg1 ;ds=_data
lea bx,parameter
cmp al,'/'
jz scanparaloop
; lea bx,parameter
; push ds
jmp error
scanparaloop:
mov [bx],al
; pop ds ;ds=psp
mov ds,cs:pspseg
lodsb
; push ds
; mov ds,cx ;ds=_data
mov ds,cs:dataseg1 ;ds=_data
cmp al,0dh
jz choise
inc bx
jnb scanparaloop ;instruction loop can not use rigister cx,
judgespace:
mov ds,cs:pspseg
lodsb
; call debug ;set break point
cmp al,0dh
je nopara
cmp al,' '
je judgespace
jne continue
nopara:
lea dx,noparamsg
jmp disp
; call disp
; call rettodos
help:
lea dx,helpmsg
jmp disp
; call disp
; call rettodos
choise:
; push cx
; mov ds,dataseg1
lea si,parameter
mov al,[si+1]
cmp al,'s'
jz savembr
cmp al,'S'
jz savembr
cmp al,'w'
jz writembr
cmp al,'W'
jz writembr
cmp al,'c'
jz savedcmosdatatohd
cmp al,'C'
jz savedcmosdatatohd
cmp al,'r'
jz reboot
cmp al,'R'
jz reboot
cmp al,'l'
jz cmoscheckedmbrld
cmp al,'L'
jz cmoscheckedmbrld
cmp al,'?'
jz help
jmp error
savembr:
; ----- Debug instrution ------
; mov ds,cs:dataseg1
; lea dx,debug
; call disp1
; mov ah,07h
; int 21h
; cli
; ------------------------------
; sub ax,ax
; pop ds ;ds=_data
; push ds
; pop es ;es=_data
mov ax,0201h
; mov bx,offset buffer
lea bx,buffer ;es:bx=_data:buffer ,es=seg _data
mov cx,0001h
mov dx,0080h
int 13h
; push bx
jb harddiskreaderr
; mov ax,_data
; mov ds,ax
; push bx
xor bx,bx
mov dx,offset filename
mov cx,0
mov ah,3ch
int 21h
jc filecreaterr
mov bx,ax
mov dx,offset buffer
; pop dx
mov cx,200h
mov ah,40h
int 21h
jc filewriteerr
mov ah,3eh
int 21h
jmp filewriteok
filecreaterr:
lea dx,filecreaterrmsg
jmp disp
; call disp
; call rettodos
filewriteerr:
lea dx,filewriteerrmsg
; call disp
; call rettodos
jmp disp
harddiskreaderr:
lea dx,hdreaderrmsg
jmp disp
; call disp
; call rettodos
filewriteok:
lea dx,filewriteokmsg
jmp disp
; call disp
; call rettodos
writembr:
; pop ds ;ds=_data
; push ds
; pop es ;es=_data
lea dx,filename
mov ax,3d00h
mov cx,0
int 21h
jc fileopenerr
mov bx,ax
mov cx,200h
lea dx,buffer
push dx
mov ah,3fh
int 21h
jc filereaderr
mov ah,3eh
int 21h
pop bx
mov ax,0301h
mov cx,0001h
mov dx,0080h
int 13h
jb hdwriteerr
jnb mbrwriteok
; jmp reboot
filereaderr:
lea dx,filereaderrmsg
jmp disp
; call disp
; call rettodos
fileopenerr:
lea dx,fileopenerrmsg
jmp disp
; call disp
; call rettodos
hdwriteerr:
lea dx,hdwriteerrmsg
jmp disp
; call disp
; call rettodos
hdreaderr:
lea dx,hdreaderrmsg
jmp disp
; call disp
; call rettodos
mbrwriteok:
lea dx,mbrwriteokmsg
call disp1
; jmp reboot
call rettodos
savedcmosdatatohd:
; mov ds,cs:[dataseg1] ;pop ds ;ds=_data seg
; push ds
; pop es ;es=_data
mov bx,offset buffer
cld
xor cx,cx
push cx
pop ax
mov cx,70h
mov al,10h
push bx ;mistake goes here,it must be push
cld
cmosdatareadloop:
out 70h,al
push ax
in al,71h
mov ds:[bx],al
pop ax
inc bx
inc al
loop cmosdatareadloop
std
pop bx ;lea bx,buffer
mov ax,0301h
; mov bx,offset buffer
mov cx,1ch ;modify the number
mov dx,0080h
int 13h
jb hdwriteerr
; jb cmossavetohdok
cmossavetohdok:
lea dx,cmossavedtohdokmsg
jmp disp
; call disp
; call rettodos
cmoscheckedmbrld:
mov ax,0201h
mov bx,offset buffer
mov cx,0001h
mov dx,0080h
int 13h
jb hdreaderr
cld
mov si,offset buffer+01beh
mov di,offset sector+01beh
mov cx,40h
repne movsb
; std
mov ax,0301h
mov bx,offset buffer
mov cx,19
mov dx,0080h
int 13h
jb hdwriteerr
lea dx,mbrbkokmsg
call disp1
mov ax,0301h
mov bx,offset sector
mov cx,0001h
mov dx,0080h
int 13h
jb hdwriteerr
lea dx,cmoscheckedmbrldokmsg
call disp1
; jmp reboot
jmp rettodos
error:
; pop ds ;ds=_data
lea dx,wrongparamsg
call disp1
mov ax,0200h
; mov si,81h
; inc si
; pop ds ;ds=psp
mov ds,cs:pspseg
; mov si,81h
pop si
dec si
prnwrongparameter:
; mov dl,ds:[si]
; cmp dl,0dh
; jz retdos
; mov ah,02h
; int 21h
; inc si
; loop prnwrongparameter
lodsb
cmp al,0dh
jz retdos
mov dl,al
; mov ah,02h
int 21h
; inc si
loop prnwrongparameter
; call disp
retdos:
mov dl,'"'
int 21h
mov dl,'!'
int 21h
jmp rettodos
reboot:
; lea bx,res
mov word ptr [bx],1234h
lea bx,dat
call dword ptr [bx]
disp:
mov ah,09h
int 21h
rettodos:
mov ah,4ch
int 21h
main endp
disp1 proc near
mov ah,09h
int 21h
ret
disp1 endp
;rettodos proc near
; mov ah,4ch
; int 21h
;rettodos endp
dataseg1 dw ?
pspseg dw ?
end start
3. 数据转换程序
/* 把二进制文件转换成汇编语言的数据文件格式 */
/* bintodat *.bin *.out */
#include <stdio.h>
#include <stdlib.h>
long filesize(FILE *stream)
{
long curpos,length;
curpos=ftell(stream);
fseek(stream,0L,SEEK_END);
length=ftell(stream);
fseek(stream,curpos,SEEK_SET);
return length;
}
int main(int argc,char * *argv)
{
FILE *fp1,*fp2;
long fsize;
unsigned i;
unsigned char tmp;
if(argc<2)
{
printf("Usage:BINTODAT [input] [output]");
exit(1);
}
fp1=fopen(argv[1],"rb");
if(fp1==NULL)
{printf("Open file %s error ",argv[1]);
exit(0);
}
fp2=fopen(argv[2],"wt");
fsize=filesize(fp1);
fprintf(fp2,"\n\tdb ");
for(i=0;i<fsize;i++)
{
tmp=fgetc(fp1);
if(tmp<0xa0)
fprintf(fp2,"%02Xh,",tmp);
else
fprintf(fp2,"%03Xh,",tmp);
if((i+1)%12==0)fprintf(fp2,"\n\tdb ");
}
printf("\nProcess O.K.");
return 0;
}