- Windows環境下32位匯編語言程序設計
- 羅云彬著
- 5638字
- 2018-12-26 20:07:10
前言
從Windows出現開始,匯編語言似乎在慢慢地銷聲匿跡,但本書可以讓人放棄這個觀點,其實在Win32環境下,匯編語言依然強大。
Why——為什么選擇Win32匯編
選擇Win32匯編的理由是什么呢?
在DOS時代,學習匯編就是學習系統底層編程的代名詞,若要成為一名入門級的匯編程序員,就需要學習從CPU結構、CPU工作方式、各種硬件的編程方法到DOS工作方式等范圍很廣的知識。隨著Windows時代的到來,Windows像一堵巨大的墻,把我們和計算機的硬件隔離開。對于DOS的匯編程序員來說,就像在一夜之間,我們發現自己曾經學過的幾乎所有的東西都被Windows封裝到內核中去了,由于保護模式的存在,我們又無法像在DOS下那樣闖入系統內核為所欲為。在Windows下用任何語言編程都必須遵循Windows的規范,匯編也不例外,也就是說,匯編不再是一種“有特權”的語言。面對洶涌而來的Visual C++,Visual Basic,PowerBuilder和Java等各個領域的猛將,從DOS時代“為所欲為”的“系統警察”崗位下崗,在其他領域又沒有一技之長,匯編語言似乎失去了生存的意義,有很多人在DOS轉向Windows的時候放棄了匯編語言。
但是經過短暫的失落,擺正了自己在系統中的位置,我們發現從“系統警察”轉換到遵循Windows規范的“好市民”后,匯編語言又慢慢地在這個世界流行起來了。畢竟,不能為所欲為也可以有好的一面,我們可以不必再考慮一些老大難的問題,如程序運行時會面對什么樣的顯示卡,如何驅動不同的打印機,內存不夠了如何用磁盤交換,等等。我們也可以在了解更少硬件知識的情況下就可以掌握Win32的匯編編程。而且,我們驚喜地發現,做了“好市民”以后,我們反而擁有了和其他語言同樣的權利——為了做圖形和界面等方面的功能,匯編程序員在DOS時代連做夢都在羨慕C語言龐大的函數庫,而現在,Windows為我們提供了比這還要多得多的函數,以至于其他大部分語言可以做出來的功能,匯編都可以做,而其他語言做不到的功能,匯編照樣可以做!所以這就是理由之一:Win32匯編可以當做一種功能強大的開發語言使用,使用它完全可以開發出大型的軟件來。
正因為Win32匯編看上去不再那樣低級,于是有讀者曾經提出:Win32匯編講的都是用API來寫程序,和高級語言差不多,以前在DOS下使用的中斷什么的都不能用,所以沒有什么新奇的了。還有讀者認為本書只不過是MSDN的匯編版本而已。言下之意就是:學匯編就是為了了解高級語言底下一層的功能,但現在Win32匯編卻使用和C++等語言相同的API接口,既然和高級語言處于同一個級別,我們為什么還要去和機器指令打交道呢,還不如去學Visual C++方便。
但是我們可以這樣問一問自己:
問:在DOS匯編中我們為什么用中斷功能?
答:為了使用DOS內核提供的功能。
問:在DOS中我們常常自己用操作I/O端口的方法讀寫硬盤或操作顯卡嗎?
答:不,我們用系統提供的int 13h和int 10h。
……
同樣,在Win32匯編里使用API也是為了使用Windows內核提供的功能。只不過使用的方式不再是中斷方式而已,這不是Win32匯編語言“高級化”了,而是高級語言因為使用Windows的API接口而“低級化”了,其代價就是無法移植到其他系統,用Visual C++寫的程序是無法移植到其他操作系統平臺上的,只有和平臺無關的ANSI C++等才能算是真正意義上的高級語言。
其實,任何匯編語言都是和操作系統密切相關的,不管是DOS匯編、Win32匯編,還是Linux匯編,都是基于特定的操作系統的,如果一定要繞過操作系統,那么就不會有DOS匯編和Win32匯編的區別了,但是這樣的話我們不是在學匯編,而是在自己開發操作系統。高級語言在不同的操作系統上看起來都差不多,但作為一種低級語言,不同操作系統上的匯編就是不同的世界。所以,既然Windows和DOS是兩個完全不同的操作系統,我們就必須拋棄DOS匯編中的大部分概念從頭開始學習Win32匯編。這就是理由之二:Win32匯編是Windows環境下一種全新的編程語言。
Win32環境下的很多高級語言,如Visual C++和Visual Basic等,一如既往地對實現的細節進行了或深或淺的封裝,就連最能表現Windows特征的部分,如消息循環和多線程的處理等內容也都被隱藏封裝,使我們在使用它們進行可視化編程的同時,無法全面了解Win32程序運行的具體方式。在學習Win32匯編以后,這些隱藏在高級語言后面的細節就暴露出來了。
由于封裝的關系,各種高級語言或多或少存在某種“缺陷”,比如VB不支持指針,結果很多需要使用指針的API用起來就很不方便,像多線程一類的特征在VB中就無法實現,PowerBuilder也是如此;C語言已經是最靈活的高級語言了,但還是無法在代碼級別處理某些需求;而匯編語言見到的是一個最真實的操作系統,它可以用最靈活的方式使用各種系統功能,第13章中有關進程隱藏的內容就是最好的寫照。所以理由之三就是:使用Win32匯編語言是了解操作系統運行細節的最佳方式。
最后的理由根本不是理由,而是必然的選擇,當我們在Windows環境下進行加密解密、逆向工程,還有病毒、木馬等有害代碼的分析和防治工作時,Win32匯編是唯一的選擇。在任何討論這方面內容的書籍中,匯編代碼的篇幅總是很大的。因此,深入了解這些內容的前提就是深入匯編編程。
How——如何學習Win32匯編
以往的匯編書籍往往把重點放在硬件結構和指令上,講述了一大堆電路框圖和指令列表,把大家搞得暈暈乎乎后,再舉出一些重量級的例子,不是一些像數組、矩陣計算一類的復雜運算,就是開始圖形模式畫圖,以至于大家看完以后就再也找不到北了!實際上,這些例子不是太難,而是太枯燥了。有人說,學匯編就像考大學,千軍萬馬過獨木橋,太多的人中途放棄了,只有少數人堅持到最后。
筆者認為:學習匯編應該在輕松的環境下進行,在學習中使用的例子不一定太復雜,但一定要有吸引力。用匯編寫復雜的運算程序固然會比C更有效率,但同樣的事在C中用一個表達式就全部搞定了,從這里開始學匯編,給人的感覺就像從復雜的公式開始學算術,要知道,加法還沒有學會呢!而對于高級語言封裝起來的系統功能,用匯編解釋起來就非常直接,非常自然,也更容易懂。以筆者自己學匯編的過程來說,那時候是1990年,剛好是中國第一次病毒大流行,大家的計算機上都是那個病毒的開山鼻祖——乒乓病毒,在流行DOS的時期,看著在屏幕上蹦的小球,心中就有一個問題:如何編出這樣一個玩意來呢?要知道DOS是單任務的,而那個球在別的程序運行的時候照樣蹦!這用當時流行的FORTRAN、C等課程中學到的任何知識都無法解釋,因為這些課程中不可能有TSR、中斷、引導區等內容。帶著這樣一個疑問學習匯編,在分析乒乓病毒的過程中啃一條條不懂的指令,病毒分析完了,匯編課也學完了,而且反過來看那些復雜的計算程序都是那么順理成章,不攻自破了。實際上,從一些實用的系統功能開始學習匯編遠比學矩陣計算容易理解。
正如最經典的C程序就是那個“Hello,World!”一樣,這個程序的有名并不是因為它用高深復雜的語句放倒了一大批人,而是它以最簡單易懂的方式讓人們走入C語言的大門。對于Win32匯編也是如此,從最簡單的例子開始總是沒錯的,筆者建議讀者跟隨本書中從簡到繁的例子,努力做到理解并靈活引用這些例子中的各種功能,正如“熟讀唐詩三百首,不會寫詩也會吟”,最后能夠熟練地使用Win32匯編來解決各種編程需求就是最大的勝利。
另外,正如前面講到的,匯編語言的學習必須和操作系統緊密結合。經過簡單的調查,筆者發現很多高校使用的匯編教程還是停留在清華91版《IBM-PC匯編語言程序設計》之類的教材上,雖然這些教材中基礎知識部分永遠不會過時,但涉及操作系統的部分還是停留在DOS階段。隨著DOS操作系統的悄然引退,繼續把精力花在上面是一種浪費,因為任何語言都必須有應用的平臺,否則課程學完之后會尷尬地發現沒有地方可以應用。筆者認為,在《IBM-PC匯編語言程序設計》之類傳統教材中的基礎部分學習完畢以后,重點就應該轉向Win32匯編,以及保護模式方面的知識。
關于本書的內容
本書嘗試從編寫應用程序的角度,從“Hello,World”這個簡單的例子開始到編寫多線程、注冊表和網絡通信等復雜的程序,通過70多個從簡單到復雜的例子,逐步深入Win32匯編編程的方方面面。筆者從事匯編編程已經有十幾年的歷史了,從8086時代的DOS匯編編程開始到當前的Win32匯編編程,從一個初學者到現在能利用Win32匯編來解決大部分編程需求,中間也經過了很長時間的摸索和大量的挫折,所以筆者很清楚初學者在哪些地方會遇到問題,但是涉及Win32匯編的書籍卻實在太少了。正是因為如此,筆者決心把本書的目標定為:能讓讀者入門并在最后能熟練掌握Win32匯編編程,而不是那種深入系統奧秘一類的書籍。
從這個目標出發,本書的選材中盡量去掉已經有其他書籍詳細討論的部分,因為要一本書涉及全部方面是不現實的。內容全面就必然不精,內容深刻就必須圍繞一個中心點,所以本書的內容并不詳細討論一般匯編教材的基礎部分,如處理器結構和保護模式等,也不準備涉及Windows驅動程序、COM編程或者其他能夠冠以“密技”頭銜的內容。本書主要的內容將放在32位宏匯編對比DOS匯編所不同的部分,以及Win32應用程序的匯編實現上。不求全面,只求精也!(說句老實話,也不敢對自己不精通的地方妄加評論,以免破壞自己的良好形象。?)
在一些匯編編程論壇上,經常有初學者問到MASM和TASM有什么不同,用哪個比較好,@@標號是什么意思,為什么用下載的匯編編譯器無法編譯程序等問題,雖然這些都屬于最基本的問題,但是以前的確沒有一個地方或者有一本書能系統全面地講解這些問題。本書的基礎篇就是因此而設的,它們是:
● 第1章 背景知識
● 第2章 準備編程環境
● 第3章 使用MASM
當搭建編譯環境和對編譯器的使用不再成為絆腳石的時候,初學者的問題往往集中在對Windows程序結構的迷惑上,消息驅動體系、窗口過程、與硬件隔絕的圖形接口及資源文件等相對于DOS程序來說都是全新的內容。接下來的4章將深入討論這些內容,通過這幾章,讀者應該開始習慣以Windows的方式考慮問題了(腦海中的DOS逐漸遠去……),這就是本書的初級篇:
● 第4章 第一個窗口程序
● 第5章 使用資源
● 第6章 定時器和Windows時間
● 第7章 圖形操作
Windows系統不像DOS系統,它的應用程序界面是規范化的,統一的界面來自大量統一的界面控件,學習這些控件就等于學習如何編寫Windows界面。下面的界面篇中的兩章將探討這方面的內容:
● 第8章 通用對話框
● 第9章 通用控件
學到這里為止,讀者應該可以寫出界面規范的標準的Win32程序了。但還是無法用這些程序來解決一些具體問題,因為有關Windows系統的高級特征的介紹還沒有開始,如內存管理、文件操作和多線程等。這些就是本書系統篇中將要介紹的內容,通過這些內容,讀者將比較深入地了解Windows的工作方式:
● 第10章 內存管理和文件操作
● 第11章 動態鏈接庫和鉤子
● 第12章 多線程
● 第13章 進程控制
● 第14章 異常處理
相信到這里為止,讀者對Windows的了解已經比較系統了。雖然Windows中還存在其他很多方面的內容,如管道,郵件槽,如何寫控制面板程序、屏幕保護程序和驅動程序等。但是有了前面的基礎以后,讀者自己去了解這些內容就不成問題了,因為掌握了“漁”,得到“魚”又有什么困難呢?在最后的幾章中,本書將從應用的角度再補充介紹一些常用的網絡編程、注冊表、PE文件和數據庫操作方面的內容,這就是應用篇:
● 第15章 注冊表和INI文件
● 第16章WinSock接口和網絡編程
● 第17章PE文件
● 第18章ODBC數據庫編程
在本書中,筆者特別以顯著的方式標出了一些經驗之談,這些是筆者在長期的匯編編程中得到的體會,可能是任何一本教科書或者手冊里都沒有的。希望這些能給讀者帶來幫助!
用“燈泡”標出的部分表示一些小技巧,對編程的理解有促進作用。
用“驚嘆號”標出的部分表示容易出錯的部分,可以幫助讀者避免一些難以理解的錯誤。
對讀者的假設
有了內容的定位,讀者的定位也就比較清楚了,本書適合于以下讀者:
● 想用Win32匯編寫Windows應用程序的讀者。
● 想從DOS下的16位匯編轉向Windows下32位匯編的讀者。
● 欲了解Win32匯編,以便為Windows下的加密解密、系統安全、逆向工程等方面打基礎的讀者。
● 欲了解Win32匯編,以便為用匯編寫Windows驅動程序打基礎的讀者。
● 正在學習匯編課程,需要補充匯編課程中Win32部分的學生。
在開始學習本書之前,讀者應該有以下的基礎知識:
● 計算機的基礎知識,如進制轉換、邏輯運算、變量類型和指針的概念等。
● 數據結構的基礎知識,因為Win32編程涉及大量的數據結構。
● C語言的基礎知識,因為Win32編程的絕大部分參考資料都是以C的格式出現的。
● Intel 80x86處理器的基礎知識,如尋址方式和指令的使用等。
本書并不是為以下讀者準備的:
● 欲詳細了解保護模式的讀者——因為Windows并不是一個開放的平臺,Windows的開放只限于應用程序接口,所以要用Windows做背景研究保護模式只能是自討苦吃,如果讀者需要深入了解這方面的內容,最好的方法就是去研究Linux的核心代碼并在Linux上實驗。
● 欲了解Windows核心“機密”的讀者——匯編并不等同于深入操作系統的內部,所以本書不是《Windows內核分析》。而真正意義上的《Windows內核分析》除了Microsoft,恐怕誰也寫不出來。
● 欲了解Windows驅動程序編寫的讀者——要介紹清楚Windows驅動程序,需要的篇幅絕不會亞于本書的篇幅,本書不打算涉及這方面的內容,讀者有興趣的話,可以閱讀《Programming WDM》和《System Programming for Windows 95》等書,前者講述的是Windows 2000/NT下的WDM驅動程序,后者講述的是Windows 9x下的VxD驅動程序。
典藏版有什么新的內容
本書第1版出版至今已經10年多了,第3版出版至今也已經3年多了,期間筆者收到了大量的讀者來信,對本書提出了各種意見和建議,綜合各方面的考慮,典藏版做了以下改進。
● 對第3版中已知的錯誤進行了修正,包括一些排版錯誤、錯別字和例子中的Bug。
● 對一些過時的內容進行了更新或刪除。
● 根據讀者的反饋,對部分章節進行了重寫。
關于附書代碼和讀者反饋
為了更好地說明Win32匯編的編程方法,本書附帶了70多個例子,這些例子的源代碼全部可以在附書光盤中找到,代碼全部采用MASM格式編寫,推薦使用的編譯軟件為MASM32 SDK軟件包。
MASM32 SDK軟件包可以在官方網站下載:http://www.masm32.com
本書中的例子代碼已經經過了嚴格的防病毒測試,絕對不含任何病毒,但第11章的例子涉及鉤子技術,第17章的例子涉及對PE文件進行操作,其中的小段代碼與一些木馬和病毒的特征碼類似,以至于被一些殺毒軟件誤認為有未知病毒,請讀者放心使用,不必顧慮。
雖然本書中所有的例子代碼都已經在32位的Windows 98、Windows 2000、Windows XP、Windows Vista和Windows 7下測試通過,但也有存在Bug的可能,如果發現代碼存在錯誤或者發現書中有其他問題,請告知作者,以便在下一個版本中改進。如果讀者有任何的反饋意見——不管是批評還是鼓勵都請和作者聯系,作者的E-mail是luoyunbin@hotmail.com。
2013年5月