汇编语言--1. 备份引导区
来源:百度文库 编辑:神马文学网 时间:2024/10/02 18:40:17
《程序设计----到田野走一走》
现今许多初学者被误导从Java、C# 什么的入门,书店也充斥着各种《24小时精通XXX》之类的书籍,使不少初学者产生错误的印象:似乎只要买这样一本书,就真有可
能在极短时间内成为高手。
前几天我看到国外的一篇文章,标题是“用十年时间学会编程”,而梁肇新在他的
《编程高手箴言》中则建议初学者从C语言入门,并且说只要有耐心的话,就有可能在
2~3年内成功。
而我个人的观点则是尽量从纯汇编入门,先扎好马步、练好基本功,这样入门会
慢一些,但你一旦掌握汇编后,再来学习C 语言就是易如反掌之事,再接下来你会发
现无论你想学习Java或者C#或者将来的D#之类,全都不在话下。
但在许多人的印象中(这些人不光初学者,甚至包括很多学习程序设计很长时间
的人,当然了,这些人极有可能就是从Java 之类入的门),汇编是极其可怕、极难学
习的。
其实不是这样的,多年来汇编难于学习其实很重要的一个原因是没有适合初学者
的书籍,国内汇编教材的传统都是一开始就画出密密麻麻的CPU电路图,再把指令系统
、寻址方式全部列出,再按顺序程序设计、循环程序设计、分支程序设计一路讲下去,
但基本上第一章就是初学者的终点站,这不得不说是一件悲哀的事。
直到2003年9月王爽的《汇编语言》出版后,这一切才发生了改变,可以说这是
国内第一本真正适合初学者入门自学的汇编教材,关于这本书,我在这里不想多说,
不然就有做广告之嫌,各位可到第二书店或互动出版网上看一看读者评论就知道了。
我今天的目的正是通过一个极小但极有趣的汇编程序,带大家到程序设计的田野
走一走,所谓田野,应该没有高楼大厦、没有水泥森林,这里只有泥土的芳香、清新
的空气...
先简单介绍一下背景知识:开机后,CPU自动转入FFFF:0000单元执行,然后执行
BIOS中的硬件检测和建立中断向量表,然后调用 int 19h 引导操作系统,如果从软盘
启动,int 19h 会将软盘0面0道1扇区共512字节读入内存0:7c00,然后跳转到0:7c00
处执行,这样操作系统就开始引导了。
我们的任务是写一个硬盘引导区备份和恢复工具,这样一个工具还是比较有用的,
因为病毒常常会破坏硬盘引导区。程序放在软盘的引导区里,通过软盘引导后,选择1
可将硬盘的引导区备份到软盘0面0道2扇区内,选择2可将软盘0面0道2扇区内备份好的
硬盘引导区恢复回去。
程序由安装部分和任务部分组成,用MASM将程序编译、链接后得到可执行的EXE
文件,然后在软驱中插入软盘,再在硬盘上执行此程序,程序中的安装部分就会将
任务部分写入软盘引导区,这样,你的备份工具盘就做好了,快备份一下你的硬盘
引导区吧,然后把软盘妥善保管好,说不定它真有派上用场的时候呢。
当然,如果你只是想体验一下,那就在虚拟机里试验一下好了。
用软盘启动并按下“1”进行备份后的画面如下:
程序里已经尽可能详细地作了注释,清单如下:
assume ds:data,cs:codesg
data segment
db 512 dup (0) ;安装程序先将任务程序复制到这里,再写入软盘
data ends
codesg segment
start:
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~安装程序~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mov ax,data
mov es,ax
mov ax,cs
mov ds,ax
;首先将引导部分复制到 es:di,即数据段 0偏移
mov si,offset br_start ;ds:si 指向任务程序
mov di,0 ;es:di 复制到这里
mov cx,offset br_end-offset br_start ;得到任务程序长度
cld
rep movsb ;开始复制
mov byte ptr es:[510],55h ;引导区末尾置 AA55h
mov byte ptr es:[511],0aah
call writedisk ;写入软盘
mov ax,4c00h
int 21h
writedisk:
mov bx,0 ;es:bx 写入的数据
mov ah,3 ;3代表写
mov al,1 ;扇区数
mov ch,0 ;磁道号
mov cl,1 ;扇区号
mov dh,0 ;碰头号
mov dl,0 ;驱动器号
int 13h
ret
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~安装程序~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~任务程序~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
br_start:
mov ax,0b800h
mov es,ax
mov cx,2000
mov bx,0
clear: ;清屏
mov byte ptr es:[bx],‘ ‘
add bx,2
loop clear
mov ax,cs
mov ds,ax
mov si,offset copyleft-offset br_start+7c00h ;显示标题
mov dl,10
mov dh,1
mov cl,14
mov bx,offset echo_str-offset br_start+7c00h
call bx
mov si,offset show_str1-offset br_start+7c00h ;显示菜单
mov dl,10
mov dh,3
mov cl,10
mov bx,offset echo_str-offset br_start+7c00h
call bx
mov si,offset show_str2-offset br_start+7c00h ;显示菜单
mov dl,10
mov dh,4
mov cl,10
mov bx,offset echo_str-offset br_start+7c00h
call bx
go:
mov ah,0 ;读取用户输入
int 16h
cmp ah,2
je $+9 ;用户选择1,即备份
cmp ah,3
je $+3bh ;用户选择2,即恢复
jmp $-0eh ;错误选择,重新输入
backup:
;ah=2 1 键
;读取硬盘引导区到内存 0000:7e00h
mov ax,0
mov es,ax
mov bx,7e00h ;es:bx 内存中的数据
mov dh,0 ;磁头号
mov ch,0 ;磁道号
mov cl,1 ;扇区号
mov al,1 ;扇区数
mov dl,80h ;驱动器号
mov ah,2 ;2代表读
int 13h
;将内存写到A 盘0面0道2扇区
mov dh,0 ;磁头号
mov ch,0 ;磁道号
mov cl,2 ;扇区号
mov al,1 ;扇区数
mov dl,0 ;驱动器号
mov ah,3 ;3代表写
int 13h
mov si,offset show_str3-offset br_start+7c00h ;显示提示信息
mov dl,10
mov dh,6
mov cl,12
mov bx,offset echo_str-offset br_start+7c00h
call bx
mov bx,offset go-offset br_start+7c00h ;等待新的输入
jmp bx
restore:
;ah=3 2 键
;读取A 盘 0面0道2扇区 到内存 0000:7e00h
mov ax,0
mov es,ax
mov bx,7e00h ;es:bx 内存中的数据
mov dh,0 ;磁头号
mov ch,0 ;磁道号
mov cl,2 ;扇区号
mov al,1 ;扇区数
mov dl,0 ;驱动器号
mov ah,2 ;2代表读
int 13h
;将内存写到硬盘引导区
mov dh,0 ;磁头号
mov ch,0 ;磁道号
mov cl,1 ;扇区号
mov al,1 ;扇区数
mov dl,80h ;驱动器号
mov ah,3 ;3代表写
int 13h
mov si,offset show_str4-offset br_start+7c00h ;显示提示信息
mov dl,10
mov dh,6
mov cl,12
mov bx,offset echo_str-offset br_start+7c00h
call bx
mov bx,offset go-offset br_start+7c00h ;等待新的输入
jmp bx
copyleft:
db ‘Harddisk Boot Sector Backup and Restore tool‘,0
show_str1:
db ‘1) Backup boot Sector to floppydisk‘,0
show_str2:
db ‘2) Restore boot Sector from floppydisk‘,0
show_str3:
db ‘Backup success,please remove floppy and restart computer...‘,0
show_str4:
db ‘Restore success,please remove floppy and restart computer...‘,0
;子函数,按给定参数显示字符串
;ds:[si] 指向字符串首地址
;dl 列,0~79
;dh 行,0~24
;cl 颜色
echo_str:
push ax ;进入子函数的第一件事,把所有子函数中用到的寄存器入栈
push bx
push cx
push si
mov ax,0b800h
mov es,ax
;根据参数计算行列
;bx=dh*160+dl*2
mov al,dh ;计算行
mov ah,160
mul ah
mov bx,ax ;保存计算结果
mov al,dl ;计算列
mov ah,2
mul ah
add bx,ax ;得到最终计算结果
mov ah,cl ;颜色
mov ch,0
s:
mov al,ds:[si]
mov cl,al
jcxz ok ;是0则退出
mov byte ptr es:[bx],al
inc bx
mov byte ptr es:[bx],ah
inc bx
inc si
jmp s
ok:
pop si ;结束子函数
pop cx
pop bx
pop ax
ret
br_end:
nop
codesg ends
end start
现今许多初学者被误导从Java、C# 什么的入门,书店也充斥着各种《24小时精通XXX》之类的书籍,使不少初学者产生错误的印象:似乎只要买这样一本书,就真有可
能在极短时间内成为高手。
前几天我看到国外的一篇文章,标题是“用十年时间学会编程”,而梁肇新在他的
《编程高手箴言》中则建议初学者从C语言入门,并且说只要有耐心的话,就有可能在
2~3年内成功。
而我个人的观点则是尽量从纯汇编入门,先扎好马步、练好基本功,这样入门会
慢一些,但你一旦掌握汇编后,再来学习C 语言就是易如反掌之事,再接下来你会发
现无论你想学习Java或者C#或者将来的D#之类,全都不在话下。
但在许多人的印象中(这些人不光初学者,甚至包括很多学习程序设计很长时间
的人,当然了,这些人极有可能就是从Java 之类入的门),汇编是极其可怕、极难学
习的。
其实不是这样的,多年来汇编难于学习其实很重要的一个原因是没有适合初学者
的书籍,国内汇编教材的传统都是一开始就画出密密麻麻的CPU电路图,再把指令系统
、寻址方式全部列出,再按顺序程序设计、循环程序设计、分支程序设计一路讲下去,
但基本上第一章就是初学者的终点站,这不得不说是一件悲哀的事。
直到2003年9月王爽的《汇编语言》出版后,这一切才发生了改变,可以说这是
国内第一本真正适合初学者入门自学的汇编教材,关于这本书,我在这里不想多说,
不然就有做广告之嫌,各位可到第二书店或互动出版网上看一看读者评论就知道了。
我今天的目的正是通过一个极小但极有趣的汇编程序,带大家到程序设计的田野
走一走,所谓田野,应该没有高楼大厦、没有水泥森林,这里只有泥土的芳香、清新
的空气...
先简单介绍一下背景知识:开机后,CPU自动转入FFFF:0000单元执行,然后执行
BIOS中的硬件检测和建立中断向量表,然后调用 int 19h 引导操作系统,如果从软盘
启动,int 19h 会将软盘0面0道1扇区共512字节读入内存0:7c00,然后跳转到0:7c00
处执行,这样操作系统就开始引导了。
我们的任务是写一个硬盘引导区备份和恢复工具,这样一个工具还是比较有用的,
因为病毒常常会破坏硬盘引导区。程序放在软盘的引导区里,通过软盘引导后,选择1
可将硬盘的引导区备份到软盘0面0道2扇区内,选择2可将软盘0面0道2扇区内备份好的
硬盘引导区恢复回去。
程序由安装部分和任务部分组成,用MASM将程序编译、链接后得到可执行的EXE
文件,然后在软驱中插入软盘,再在硬盘上执行此程序,程序中的安装部分就会将
任务部分写入软盘引导区,这样,你的备份工具盘就做好了,快备份一下你的硬盘
引导区吧,然后把软盘妥善保管好,说不定它真有派上用场的时候呢。
当然,如果你只是想体验一下,那就在虚拟机里试验一下好了。
用软盘启动并按下“1”进行备份后的画面如下:
程序里已经尽可能详细地作了注释,清单如下:
assume ds:data,cs:codesg
data segment
db 512 dup (0) ;安装程序先将任务程序复制到这里,再写入软盘
data ends
codesg segment
start:
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~安装程序~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mov ax,data
mov es,ax
mov ax,cs
mov ds,ax
;首先将引导部分复制到 es:di,即数据段 0偏移
mov si,offset br_start ;ds:si 指向任务程序
mov di,0 ;es:di 复制到这里
mov cx,offset br_end-offset br_start ;得到任务程序长度
cld
rep movsb ;开始复制
mov byte ptr es:[510],55h ;引导区末尾置 AA55h
mov byte ptr es:[511],0aah
call writedisk ;写入软盘
mov ax,4c00h
int 21h
writedisk:
mov bx,0 ;es:bx 写入的数据
mov ah,3 ;3代表写
mov al,1 ;扇区数
mov ch,0 ;磁道号
mov cl,1 ;扇区号
mov dh,0 ;碰头号
mov dl,0 ;驱动器号
int 13h
ret
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~安装程序~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~任务程序~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
br_start:
mov ax,0b800h
mov es,ax
mov cx,2000
mov bx,0
clear: ;清屏
mov byte ptr es:[bx],‘ ‘
add bx,2
loop clear
mov ax,cs
mov ds,ax
mov si,offset copyleft-offset br_start+7c00h ;显示标题
mov dl,10
mov dh,1
mov cl,14
mov bx,offset echo_str-offset br_start+7c00h
call bx
mov si,offset show_str1-offset br_start+7c00h ;显示菜单
mov dl,10
mov dh,3
mov cl,10
mov bx,offset echo_str-offset br_start+7c00h
call bx
mov si,offset show_str2-offset br_start+7c00h ;显示菜单
mov dl,10
mov dh,4
mov cl,10
mov bx,offset echo_str-offset br_start+7c00h
call bx
go:
mov ah,0 ;读取用户输入
int 16h
cmp ah,2
je $+9 ;用户选择1,即备份
cmp ah,3
je $+3bh ;用户选择2,即恢复
jmp $-0eh ;错误选择,重新输入
backup:
;ah=2 1 键
;读取硬盘引导区到内存 0000:7e00h
mov ax,0
mov es,ax
mov bx,7e00h ;es:bx 内存中的数据
mov dh,0 ;磁头号
mov ch,0 ;磁道号
mov cl,1 ;扇区号
mov al,1 ;扇区数
mov dl,80h ;驱动器号
mov ah,2 ;2代表读
int 13h
;将内存写到A 盘0面0道2扇区
mov dh,0 ;磁头号
mov ch,0 ;磁道号
mov cl,2 ;扇区号
mov al,1 ;扇区数
mov dl,0 ;驱动器号
mov ah,3 ;3代表写
int 13h
mov si,offset show_str3-offset br_start+7c00h ;显示提示信息
mov dl,10
mov dh,6
mov cl,12
mov bx,offset echo_str-offset br_start+7c00h
call bx
mov bx,offset go-offset br_start+7c00h ;等待新的输入
jmp bx
restore:
;ah=3 2 键
;读取A 盘 0面0道2扇区 到内存 0000:7e00h
mov ax,0
mov es,ax
mov bx,7e00h ;es:bx 内存中的数据
mov dh,0 ;磁头号
mov ch,0 ;磁道号
mov cl,2 ;扇区号
mov al,1 ;扇区数
mov dl,0 ;驱动器号
mov ah,2 ;2代表读
int 13h
;将内存写到硬盘引导区
mov dh,0 ;磁头号
mov ch,0 ;磁道号
mov cl,1 ;扇区号
mov al,1 ;扇区数
mov dl,80h ;驱动器号
mov ah,3 ;3代表写
int 13h
mov si,offset show_str4-offset br_start+7c00h ;显示提示信息
mov dl,10
mov dh,6
mov cl,12
mov bx,offset echo_str-offset br_start+7c00h
call bx
mov bx,offset go-offset br_start+7c00h ;等待新的输入
jmp bx
copyleft:
db ‘Harddisk Boot Sector Backup and Restore tool‘,0
show_str1:
db ‘1) Backup boot Sector to floppydisk‘,0
show_str2:
db ‘2) Restore boot Sector from floppydisk‘,0
show_str3:
db ‘Backup success,please remove floppy and restart computer...‘,0
show_str4:
db ‘Restore success,please remove floppy and restart computer...‘,0
;子函数,按给定参数显示字符串
;ds:[si] 指向字符串首地址
;dl 列,0~79
;dh 行,0~24
;cl 颜色
echo_str:
push ax ;进入子函数的第一件事,把所有子函数中用到的寄存器入栈
push bx
push cx
push si
mov ax,0b800h
mov es,ax
;根据参数计算行列
;bx=dh*160+dl*2
mov al,dh ;计算行
mov ah,160
mul ah
mov bx,ax ;保存计算结果
mov al,dl ;计算列
mov ah,2
mul ah
add bx,ax ;得到最终计算结果
mov ah,cl ;颜色
mov ch,0
s:
mov al,ds:[si]
mov cl,al
jcxz ok ;是0则退出
mov byte ptr es:[bx],al
inc bx
mov byte ptr es:[bx],ah
inc bx
inc si
jmp s
ok:
pop si ;结束子函数
pop cx
pop bx
pop ax
ret
br_end:
nop
codesg ends
end start
汇编语言--1. 备份引导区
汇编语言
制作GRUB启动软盘/备份恢复硬盘引导程序
备份/恢复MBR和分区表,以及无备份修复MBR及分区表错误;浅谈引导故障和分区方案
汇编语言超浓缩教程
简明x86汇编语言教程
汇编语言超浓缩教程
汇编语言超浓缩教程
ARM汇编语言伪指令
Linux 汇编语言开发指南
汇编语言数字滤波
Linux 汇编语言开发指南
汇编语言超浓缩教程
ARM汇编语言伪指令
汇编语言指令英文全称
《汇编语言》指令一览表
1.数据库高级备份还原(续)
硬盘引导区修复与Fixmbr命令
汇编语言上机指导及例示
单片机汇编语言实现DES加密算法
汇编语言数据传送指令MOV
汇编语言延时时间的计算
简明x86汇编语言教程(3)
简明x86汇编语言教程(5)