x86匯編語言教程(1)
----獻(xiàn)給教PC技術(shù)的朋友!
我不想夸大或者貶低匯編語言。但我想說,匯編語言改變了20世紀(jì)的歷史。與前輩相比,我們這一代編程人員足夠的幸福,因?yàn)槲覀冇懈魇礁鳂拥木幊陶Z言,我們可以操作鍵盤、坐在顯示器面前,甚至使用鼠標(biāo)、語音識(shí)別。我們可以使用鍵盤、鼠標(biāo)來駕馭“個(gè)人計(jì)算機(jī)”,而不是和一群人共享一臺(tái)使用笨重的繼電器、開關(guān)去操作的巨型機(jī)。相比之下,我們的前輩不得不使用機(jī)器語言編寫程序,他們甚至沒有最簡單的匯編程序來把助記符翻譯成機(jī)器語言,而我們可以從上千種計(jì)算機(jī)語言中選擇我們喜歡的一種,而匯編,雖然不是一種“常用”的具有“快速原型開發(fā)”能力的語言,卻也是我們可以選擇的語言中的一種。
每種計(jì)算機(jī)都有自己的匯編語言——沒必要指望匯編語言的可移植性,選擇匯編,意味著選擇性能而不是可移植或便于調(diào)試。這份文檔中講述的是x86匯編語言,此后的“匯編語言”一詞,如果不明示則表示ia32上的x86匯編語言。
匯編語言是一種易學(xué),卻很難精通的語言;叵氘(dāng)年,我從初學(xué)匯編到寫出第一個(gè)可運(yùn)行的程序,只用了不到4個(gè)小時(shí);然而直到今天,我仍然不敢說自己精通它。編寫快速、高效、并且能夠讓處理器“很舒服地執(zhí)行”的程序是一件很困難的事情,如果利用業(yè)余時(shí)間學(xué)習(xí),通常需要2-3年的時(shí)間才能做到。這份教材并不期待能夠教給你大量的匯編語言技巧。對于讀者來說,x86匯編語言"就在這里"。然而,不要僵化地局限于這份教材講述的內(nèi)容,因?yàn)樗荒芨嬖V你匯編語言是“這樣一回事”。學(xué)好匯編語言,更多的要靠一個(gè)人的創(chuàng)造力于悟性,我可以告訴你我所知道的技巧,但肯定這是不夠的。一位對我的編程生涯產(chǎn)生過重要影響的人曾經(jīng)對我說過這么一句話:
寫匯編語言程序不是匯編語言最難的部分,創(chuàng)新才是。 |
我想,愿意看這份文檔的人恐怕不會(huì)問我“為什么要學(xué)習(xí)匯編語言”這樣的問題;不過,我還是想說幾句:首先,匯編語言非常有用,我個(gè)人主張把它作為C語言的先修課程,因?yàn)橥ㄟ^學(xué)習(xí)匯編語言,你可以了解到如何有效地設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu),讓計(jì)算機(jī)處理得更快,并使用更少的存儲(chǔ)空間;同時(shí),學(xué)習(xí)匯編語言可以讓你熟悉計(jì)算機(jī)內(nèi)部運(yùn)行機(jī)制,并且,有效地提高調(diào)試能力。就我個(gè)人的經(jīng)驗(yàn)而言,調(diào)試一個(gè)非結(jié)構(gòu)化的程序的困難程度,要比調(diào)試一個(gè)結(jié)構(gòu)化的程序的難度高很多,因?yàn)椤敖Y(jié)構(gòu)化”是以犧牲運(yùn)行效率來提高可讀性與可調(diào)試性,這對于完成一般軟件工程的編碼階段是非常必要的。然而,在一些地方,比如,硬件驅(qū)動(dòng)程序、操作系統(tǒng)底層,或者程序中經(jīng)常需要執(zhí)行的代碼,結(jié)構(gòu)化程序設(shè)計(jì)的這些優(yōu)點(diǎn)有時(shí)就會(huì)被它的低效率所抹煞。另外,如果你想真正地控制自己的程序,只知道源代碼級的調(diào)試是遠(yuǎn)遠(yuǎn)不夠的。
浮躁的人喜歡說,用C++寫程序足夠了,甚至說,他不僅僅掌握C++,而且精通STL、MFC。我不贊成這個(gè)觀點(diǎn),掌握上面的那些是每一個(gè)編程人員都應(yīng)該做到的,然而C++只是我們"常用"的一種語言,它不是編程的全部。低層次的開發(fā)者喜歡說,嘿,C++是多么的強(qiáng)大,它可以做任何事情——這不是事實(shí)。便于維護(hù)、調(diào)試,這些確實(shí)是我們的追求目標(biāo),但是,寫程序不能僅僅追求這個(gè)目標(biāo),因?yàn)槲覀冏罱K的目的是滿足設(shè)計(jì)需求,而不是個(gè)人非理性的理想。
這份教材適合已經(jīng)學(xué)習(xí)過某種結(jié)構(gòu)化程序設(shè)計(jì)語言的讀者。其內(nèi)容基于我在1995年給別人講述匯編語言時(shí)所寫的講義。當(dāng)然,如大家所希望的,它包含了最新的處理器所支持的特性,以及相應(yīng)的內(nèi)容。我假定讀者已經(jīng)知道了程序設(shè)計(jì)的一些基本概念,因?yàn)闆]有這些是無法理解匯編語言程序設(shè)計(jì)的;此外,我希望讀者已經(jīng)有了比較良好的程序設(shè)計(jì)基礎(chǔ),因?yàn)槿绻闳狈τ诮Y(jié)構(gòu)化程序設(shè)計(jì)的認(rèn)識(shí),編寫匯編語言程序很可能很快就破壞了你的結(jié)構(gòu)化編程習(xí)慣,大大降低程序的可讀性、可維護(hù)性,最終讓你的程序陷于不得不廢棄的代碼堆之中。
基本上,這份文檔撰寫的目標(biāo)是盡可能地便于自學(xué)。不過,它對你也有一些要求,盡管不是很高,但我還是強(qiáng)調(diào)一下。
|
祝您編程愉快!
先說一點(diǎn)和實(shí)際編程關(guān)系不太大的東西。當(dāng)然,如果你迫切的想看到更實(shí)質(zhì)的內(nèi)容,完全可以先跳過這一章。
那么,我想可能有一個(gè)問題對于初學(xué)匯編的人來說非常重要,那就是:
匯編語言到底是什么?
匯編語言是一種最接近計(jì)算機(jī)核心的編碼語言。不同于任何高級語言,匯編語言幾乎可以完全和機(jī)器語言一一對應(yīng)。不錯(cuò),我們可以用機(jī)器語言寫程序,但現(xiàn)在除了沒有匯編程序的那些電腦之外,直接用機(jī)器語言寫超過1000條以上指令的人大概只能算作那些被我們成為“圣人”的犧牲者一類了。畢竟,記憶一些短小的助記符、由機(jī)器去考慮那些瑣碎的配位過程和檢查錯(cuò)誤,比記憶大量的隨計(jì)算機(jī)而改變的十六進(jìn)制代碼、可能弄錯(cuò)而沒有任何提示要強(qiáng)的多。熟練的匯編語言編碼員甚至可以直接從十六進(jìn)制代碼中讀出匯編語言的大致意思。當(dāng)然,我們有更好的工具——匯編器和反匯編器。
簡單地說,匯編語言就是機(jī)器語言的一種可以被人讀懂的形式,只不過它更容易記憶。至于宏匯編,則是包含了宏支持的匯編語言,這可以讓你編程的時(shí)候更專注于程序本身,而不是忙于計(jì)算和重寫代碼。
匯編語言除了機(jī)器語言之外最接近計(jì)算機(jī)硬件的編程語言。由于它如此的接近計(jì)算機(jī)硬件,因此,它可以最大限度地發(fā)揮計(jì)算機(jī)硬件的性能。用匯編語言編寫的程序的速度通常要比高級語言和C/C++快很多--幾倍,幾十倍,甚至成百上千倍。當(dāng)然,解釋語言,如解釋型LISP,沒有采用JIT技術(shù)的Java虛機(jī)中運(yùn)行的Java等等,其程序速度更無法與匯編語言程序同日而語 。
永遠(yuǎn)不要忽視匯編語言的高速。實(shí)際的應(yīng)用系統(tǒng)中,我們往往會(huì)用匯編徹底重寫某些經(jīng)常調(diào)用的部分以期獲得更高的性能。應(yīng)用匯編也許不能提高你的程序的穩(wěn)定性,但至少,如果你非常小心的話,它也不會(huì)降低穩(wěn)定性;與此同時(shí),它可以大大地提高程序的運(yùn)行速度。我強(qiáng)烈建議所有的軟件產(chǎn)品在最后Release之前對整個(gè)代碼進(jìn)行Profile,并適當(dāng)?shù)赜脜R編取代部分高級語言代碼。至少,匯編語言的知識(shí)可以告訴你一些有用的東西,比如,你有多少個(gè)寄存器可以用。有時(shí),手工的優(yōu)化比編譯器的優(yōu)化更為有效,而且,你可以完全控制程序的實(shí)際行為。
我想我在羅嗦了?傊谖覀兘Y(jié)束這一章之前,我想說,不要在優(yōu)化的時(shí)候把希望完全寄托在編譯器上——現(xiàn)實(shí)一些,再好的編譯器也不可能總是產(chǎn)生最優(yōu)的代碼。