現今許多初學(xué)者被誤導從Java、C# 什么的入門(mén),書(shū)店也充斥著(zhù)各種《24小時(shí)精通XXX》之類(lèi)的書(shū)籍,使不少初學(xué)者產(chǎn)生錯誤的印象:似乎只要買(mǎi)這樣一本書(shū),就真有可
能在極短時(shí)間內成為高手。
前幾天我看到國外的一篇文章,標題是“用十年時(shí)間學(xué)會(huì )編程”,而梁肇新在他的
《編程高手箴言》中則建議初學(xué)者從C語(yǔ)言入門(mén),并且說(shuō)只要有耐心的話(huà),就有可能在
2~3年內成功。
而我個(gè)人的觀(guān)點(diǎn)則是盡量從純匯編入門(mén),先扎好馬步、練好基本功,這樣入門(mén)會(huì )
慢一些,但你一旦掌握匯編后,再來(lái)學(xué)習C 語(yǔ)言就是易如反掌之事,再接下來(lái)你會(huì )發(fā)
現無(wú)論你想學(xué)習Java或者C?;蛘邔?lái)的D#之類(lèi),全都不在話(huà)下。
但在許多人的印象中(這些人不光初學(xué)者,甚至包括很多學(xué)習程序設計很長(cháng)時(shí)間
的人,當然了,這些人極有可能就是從Java 之類(lèi)入的門(mén)),匯編是極其可怕、極難學(xué)
習的。
其實(shí)不是這樣的,多年來(lái)匯編難于學(xué)習其實(shí)很重要的一個(gè)原因是沒(méi)有適合初學(xué)者
的書(shū)籍,國內匯編教材的傳統都是一開(kāi)始就畫(huà)出密密麻麻的CPU電路圖,再把指令系統
、尋址方式全部列出,再按順序程序設計、循環(huán)程序設計、分支程序設計一路講下去,
但基本上第一章就是初學(xué)者的終點(diǎn)站,這不得不說(shuō)是一件悲哀的事。
直到2003年9月王爽的《匯編語(yǔ)言》出版后,這一切才發(fā)生了改變,可以說(shuō)這是
國內第一本真正適合初學(xué)者入門(mén)自學(xué)的匯編教材,關(guān)于這本書(shū),我在這里不想多說(shuō),
不然就有做廣告之嫌,各位可到第二書(shū)店或互動(dòng)出版網(wǎng)上看一看讀者評論就知道了。
我今天的目的正是通過(guò)一個(gè)極小但極有趣的匯編程序,帶大家到程序設計的田野
走一走,所謂田野,應該沒(méi)有高樓大廈、沒(méi)有水泥森林,這里只有泥土的芳香、清新
的空氣...
先簡(jiǎn)單介紹一下背景知識:開(kāi)機后,CPU自動(dòng)轉入FFFF:0000單元執行,然后執行
BIOS中的硬件檢測和建立中斷向量表,然后調用 int 19h 引導操作系統,如果從軟盤(pán)
啟動(dòng),int 19h 會(huì )將軟盤(pán)0面0道1扇區共512字節讀入內存0:7c00,然后跳轉到0:7c00
處執行,這樣操作系統就開(kāi)始引導了。
我們的任務(wù)是寫(xiě)一個(gè)硬盤(pán)引導區備份和恢復工具,這樣一個(gè)工具還是比較有用的,
因為病毒常常會(huì )破壞硬盤(pán)引導區。程序放在軟盤(pán)的引導區里,通過(guò)軟盤(pán)引導后,選擇1
可將硬盤(pán)的引導區備份到軟盤(pán)0面0道2扇區內,選擇2可將軟盤(pán)0面0道2扇區內備份好的
硬盤(pán)引導區恢復回去。
程序由安裝部分和任務(wù)部分組成,用MASM將程序編譯、鏈接后得到可執行的EXE
文件,然后在軟驅中插入軟盤(pán),再在硬盤(pán)上執行此程序,程序中的安裝部分就會(huì )將
任務(wù)部分寫(xiě)入軟盤(pán)引導區,這樣,你的備份工具盤(pán)就做好了,快備份一下你的硬盤(pán)
引導區吧,然后把軟盤(pán)妥善保管好,說(shuō)不定它真有派上用場(chǎng)的時(shí)候呢。
當然,如果你只是想體驗一下,那就在虛擬機里試驗一下好了。
用軟盤(pán)啟動(dòng)并按下“1”進(jìn)行備份后的畫(huà)面如下:
程序里已經(jīng)盡可能詳細地作了注釋?zhuān)鍐稳缦拢?span lang="EN-US" twffan="done">
assume ds:data,cs:codesg
data segment
db 512 dup (0) ;安裝程序先將任務(wù)程序復制到這里,再寫(xiě)入軟盤(pán)
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 指向任務(wù)程序
mov di,0 ;es:di 復制到這里
mov cx,offset br_end-offset br_start ;得到任務(wù)程序長(cháng)度
cld
rep movsb ;開(kāi)始復制
mov byte ptr es:[510],55h ;引導區末尾置 AA55h
mov byte ptr es:[511],0aah
call writedisk ;寫(xiě)入軟盤(pán)
mov ax,4c00h
int 21h
writedisk:
mov bx,0 ;es:bx 寫(xiě)入的數據
mov ah,3 ;3代表寫(xiě)
mov al,1 ;扇區數
mov ch,0 ;磁道號
mov cl,1 ;扇區號
mov dh,0 ;碰頭號
mov dl,0 ;驅動(dòng)器號
int 13h
ret
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~安裝程序~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~任務(wù)程序~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 ;讀取用戶(hù)輸入
int 16h
cmp ah,2
je $+9 ;用戶(hù)選擇1,即備份
cmp ah,3
je $+3bh ;用戶(hù)選擇2,即恢復
jmp $-0eh ;錯誤選擇,重新輸入
backup:
;ah=2 1 鍵
;讀取硬盤(pán)引導區到內存 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 ;驅動(dòng)器號
mov ah,2 ;2代表讀
int 13h
;將內存寫(xiě)到A 盤(pán)0面0道2扇區
mov dh,0 ;磁頭號
mov ch,0 ;磁道號
mov cl,2 ;扇區號
mov al,1 ;扇區數
mov dl,0 ;驅動(dòng)器號
mov ah,3 ;3代表寫(xiě)
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 盤(pán) 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 ;驅動(dòng)器號
mov ah,2 ;2代表讀
int 13h
;將內存寫(xiě)到硬盤(pán)引導區
mov dh,0 ;磁頭號
mov ch,0 ;磁道號
mov cl,1 ;扇區號
mov al,1 ;扇區數
mov dl,80h ;驅動(dòng)器號
mov ah,3 ;3代表寫(xiě)
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 ;進(jìn)入子函數的第一件事,把所有子函數中用到的寄存器入棧
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
聯(lián)系客服