作者簡介
Jeff Duntemann,是一位在科幻文學與技術領域皆有建樹的知名作家,發表技術文章 逾百篇;現為技術出版顧問兼Copperwood Press獨立出版人。Jeff迄今已撰寫20本技術書籍。Jeff曾在Dr Dobb's Journal 雜誌撰寫”結構化程式設計”專欄達四年之久,並在其他雜誌上發表了數十篇技術文章 。其作品以技術深度與敘事魅力的完美融合著稱。
前言/序言
感謝在本書撰寫和出版過程中以各種方式説明我的所有人。首先感謝Wiley的Jim Minatel和Pete Gaughan,他們啟動了這個項目並確保了項目的完成。還要感謝David Stafford,他擔任技術編輯並不斷提出寶貴的建議。
GitHub的Antony成功創建了一個適用於Linux的AppImage版本,用於古怪、過時但非常易用的Insight調試器;該調試器在本書第3版於2009年出版後不久就從Linux存儲庫中移除了。非常感謝Antony完成了這個非常特別的項目。你可以在此找到他的Insight AppImage:https: appimage github io/Insight。
還要特別感謝Dmitriy Manushin,他創建了SASM,這是一個面向初學者的免費組合語言整合式開發環境(IDE):https: dman95 github io/SASM/english html。
當我在glibc中遇到奇怪的問題時,Contrapositive Diary上的專家團隊幫我解決了問題:
Jim Strickland
Bill Buhler
Jason Bucata
Jonathan O’Neal
Bruce和Keith(沒有留下姓氏,沒關係——建議很寶貴)
最後,和往常一樣,我要向Carol致敬。感謝她54年來的支持和珍貴友誼,這不僅讓我充滿活力,還讓我有能力承擔這樣充滿挑戰的項目,並堅持到底,無論這些項目一路上讓我多麼抓狂!
前言
“你為什麼要那樣做?”
那是1985年,我在紐約市乘坐包車去參加一個新聞發佈會,同行的還有一群焦躁不安的媒體狂人。我當時剛剛開始我的科技記者生涯(擔任PC Tech Journal的技術編輯),我的第一本書還要幾個月後才會問世。碰巧,我坐在一位著名的程式設計作家/專家旁邊,我對他印象深刻,因為他一直在對我嘮叨一些事情。他確實很煩人,但我現在才明白為什麼他那麼令人討厭:他的生活和工作與我完全沒有交集。
在我們的聊天中,我無意中透露了我是一個Turbo Pascal狂熱愛好者,而我真正想做的是學習如何編寫利用全新Microsoft Windows使用者介面的Turbo Pascal程式。他皺了皺鼻子,苦笑了一下,然後問出了那個著名的問題:
“你為什麼要那樣做?”
那時我還從未聽過這個問題(儘管後來我聽到了很多次),這讓我很驚訝。”為什麼?因為,嗯,因為我想知道它是如何工作的。”我這樣想著,於是答道,
“呵呵,那就是C語言的用途。”
進一步的討論並沒有讓我在Pascal的方向上有所進展。但經過一番探索,我明白了不能用Turbo Pascal編寫Windows應用程式。這是不可能的。或者那位程式設計作家/專家不知道怎麼做。也許兩者皆有。我從未瞭解過1985年的真實情況。Delphi在1995年徹底解答了這個問題。但我確實瞭解了那個著名問題的含義。
請注意,如果有人問你:”你為什麼要那樣做?”它的真正意思是:你問我如何做一件事情,這件事要麼不可能用我偏愛的工具實現,要麼完全超出了我的經驗範圍,但我不想通過承認這一點而失去面子。
這些年來我一次又一次聽到這樣的話:
問:如何設置C字串,以便不必掃描即可讀取其長度?
答:你為什麼要那樣做?
問:如何編寫可從Turbo Pascal調用的組合語言副程式?
答:你為什麼要那樣做?
問:如何用組合語言編寫Windows應用程式?
答:你為什麼要那樣做?
你明白這個意思了。對於這個著名的問題,答案永遠都是一樣的。如果那些狡猾的人問你這個問題,你就儘快反擊:”因為我想知道它是如何運作的。”
這是一個完全足夠的回答。每次我都用這個答案,除了很多年前的一個例外,那時我提出我想寫一本書,教人們如何將組合語言程式設計作為他們的第一次程式設計體驗。
問:天哪,你為什麼要那樣做?
答:因為這是培養理解程式設計世界其他部分如何運作所需技能的最佳方式。
成為一名程式師,首先要做到的一點是理解事物的工作原理。此外,學習成為一名程式師幾乎完全是一個瞭解事物如何運作的過程。這可以在不同層次上完成,具體取決於你使用的工具。
如果你使用的是Visual Basic程式設計,你需要理解某些事物的工作原理,但這些事物基本上都局限於Visual Basic本身。Visual Basic在程式師與電腦之間設置了一道屏障,隱藏了大量的底層機制。Delphi、Lazarus、Java、Python及許多其他高級程式設計環境也是如此。如果你使用的是C編譯器,你會離機器更近,你會看到更多的底層機制——因此,你必須理解這些機制的工作原理才能使用它們。然而,即使是資深的C程式師,也有許多東西仍然隱藏在他們的視野之外。
一方面,如果你在使用組合語言程式設計,你會盡可能地接近機器。組合語言不隱藏任何東西,也不會保留任何能力。當然,另一方面,你和機器之間沒有任何神奇的層可以消除任何無知並且可以”處理”一切。如果你不理解某些東西的工作原理,你就會陷入困境——除非你足夠瞭解,能夠自己弄明白。
這是一個關鍵點:我編寫本書的目標並非僅是講授組合語言本身。如果說本書有一個首要目標的話,那就是讓你對機器底層產生一定的好奇心,同時提供一些基本的背景知識,幫助你開始探索機器的最底層,以及給予你信心去盡力嘗試。這是困難的地方,但只要你集中注意力、耐心等待並投入必要的時間(可能會相當長),你完全可以掌握它。
實際上,我真正教給你的,是如何去學習。
你需要什麼
要按照我所講授的方式進行程式設計,你需要一台運行64位元Linux發行版本的英特爾電腦。我在編寫這本書時使用的是Linux Mint Cinnamon V20 3 Una。Una是這個Linux Mint版本的代碼名稱,是”Linux Mint 20 3”的簡寫。我推薦使用Mint;它給我帶來的麻煩比我用過的任何其他發行版本都少,而且自從Linux首次出現以來,我就斷斷續續地使用它。我認為你選擇哪個圖形化shell並不重要。我喜歡Cinnamon,你可以使用自己喜歡或熟悉的任何介面。
你需要在使用者級別上對Linux有一定的熟練掌握能力。我無法在本書中教你如何安裝、配置和運行Linux。如果你還不熟悉Linux,請找一本教程,學習並掌握它。網上有很多這樣的教程。
你需要一款名為SASM的免費軟體,這是一種簡單的彙編程式設計互動式開發環境。它基本上包括一個編輯器、一個構建系統,以及一個標準Linux調試器gdb的前端。你還需要一個免費的彙編器,名為NASM。
你不需要提前知道如何下載、安裝和配置這些工具,因為在適當的時機,我會詳細介紹所有必要的工具安裝和配置方式。
請注意,其他不基於Linux內核的UNIX實現可能在底層的工作方式上有所不同。例如,BSD UNIX在進行系統調用時使用了不同的約定,而其他UNIX版本(如Solaris)則超出了我的經驗範圍。
請記住,本書是關於x64架構的。在x64的範圍內,我也會講解x86架構的元素。32位x86和64位x64之間的差距比16位x86和32位x86之間的差距要小得多。如果你已經扎實掌握了32位x86的基礎知識,你將很快掌握本書的大部分內容。如果你能做到這一點,那很好——只是請記住,本書是為了那些剛剛開始在英特爾CPU上程式設計的人準備的。
還要記住,這本書的版面受出版商的限制:紙張、油墨和裝訂都不免費。這意味著我必須在這些限制內縮小我講授和解釋的內容範圍。我希望有足夠的篇幅來介紹AVX數學子系統,而實際上沒有。但是,我相信,一旦你讀完這本書,就能搞清楚其中的大部分內容。
總體規劃
本書從最基礎的知識開始講解。也許你在這個階段,已經完全掌握了這些。我尊重這一點。我仍然認為,從第1章 開始,一直到最後一章 按順序閱讀不會有什麼壞處。複習是有用的,你可能會意識到你對某些內容的瞭解沒有你想像的那麼深刻(這種情況經常發生在我身上)。
如果時間緊迫,可以按照下面的建議進行學習:
如果你已經瞭解電腦程式設計的基本思想,請跳過第1章 。
如果你已經瞭解十進位以外的其他數字進制(尤其是十六進位和二進位)背後的思想,請跳過第2章 。
如果你已經掌握了電腦的內部結構(記憶體、CPU架構等),請跳過第3章 。
如果你已經瞭解x64記憶體定址,請跳過第4章 。
不。停下來。即使你已經瞭解x64記憶體定址,也請閱讀第4章 。
最後一項需要特別強調一下,原因是:組合語言程式設計涉及記憶體定址。如果你不理解記憶體定址,那麼你在組合語言中學到的其他任何知識都不會對你有幫助。所以,無論你已經知道或認為自己知道什麼,都不要跳過第4章 。從那裡開始,一直到最後。記憶體定址在書的其餘部分會經常出現,它實際上是組合語言程式設計的核心。
載入每個示例程式,彙編每個程式,並運行它們。努力理解每個程式中的每一行。不要盲目相信任何東西。此外,別僅僅停留於此。隨著你對事物的理解加深,可修改示例程式。嘗試不同的方法,嘗試一些我沒有提到的做法,要大膽,可以盡情嘗試。最糟糕的情況只是Linux拋出一個分段錯誤,這可能損壞你的程式,但不會損害Linux。唯一的注意事項是,當你嘗試某些做法時,儘量理解為什麼它沒有像你理解的其他有效事物那樣井井有條地工作。即使程式運行正常,也要在SASM調試器中逐步調試。
這就是我最終追求的目標:展示如何理解機器的每一個細節 是如何運作的,以及它的所有元件是如何協同工作的。這並不意味著我會親自解釋它的每一個細節 ——因為沒有人能活得足夠久去做到這一點,而且電腦技術已經不再簡單了。如果你已經養成耐心研究和實驗的習慣,你可以自己弄明白。歸根結底,這就是學習的唯一途徑:靠自己。從朋友、網路或像這樣的書籍中得到的指導只是引導和潤滑劑。你必須決定誰才是主宰,是你還是機器,並使之成為現實。
關於大寫慣例的說明
組合語言在程式設計語言中有一個獨特之處,即沒有統一的大小寫區分標準。在C語言中,所有識別字都區分大小寫,而我見過一些彙編器完全不區分大小寫。本書介紹的彙編器NASM,僅對程式師定義的識別字區分大小寫,指令助記符和寄存器名稱是不區分大小寫的。
組合語言文獻中有一個習慣,那就是在章 節 描述中將CPU指令助記符用大寫字母表示,而原始程式碼檔和文本中的程式碼片段用小寫字母表示。本書也會遵循這一習慣。在正文中,會使用MOV、CALL和CMP;而在示例代碼中,則使用mov、call和cmp。代碼片段和代碼清單將以等寬的Courier風格字體呈現。當提到寄存器時,會使用大寫字母(但不使用Courier字體),而在代碼片段和清單中則使用小寫字母。
在正文中,助記符需要突出顯示(用大寫字母)。在一大堆普通的大小寫字母混合的單詞中,很容易忘記它們。
要閱讀和學習本書以外的現有文檔和原始程式碼,你需要能夠輕鬆地閱讀大寫、小寫以及混合大小寫的組合語言。熟悉不同的表達方式非常重要。
記住你為什麼在這裡
不管你選擇從書的哪一部分開始,現在是時候開始了。只要記住,假如遇到困難,無論是面對微妙的問題還是面對機器故障,你要始終把這個目標放在心中:要努力搞清楚它是如何運作的。
讓我們一起出發吧。
原始程式碼下載
可掃描封底二維碼,下載原始程式碼。
詳細資料或其他書籍請至台灣高等教育出版社查詢,查後請於客服中心或Line或本社留言板留言,我們即儘速上架。