工作三年餘,發現精力會隨著諸多瑣事而消耗,曾經充滿激情與興趣的技術探索,漸漸變得「無關緊要」。這究竟是一種看透後的灑脫,還是懈怠的藉口?無論如何,我決定克服現狀,充實業餘時光。加上近期獲得「准專家徽章」,為了不負這份榮譽,也為了擺脫倦怠,我堅持記錄下這些思考。
先前在網路上,一群同行正討論「C/C++ 程式設計師是否應具備一定程度的組合語言功底」。作為一名 C/C++ 開發者,我自然參與其中。這個問題觸動了我的親身感受與經驗,趁著中秋假期有空,便想系統性地分享一下個人觀點。先聲明:文中僅代表個人見解,認同者欣慰,不認同者當作閱讀小說消遣即可。技術無絕對對錯,我一貫秉持「吸收對我有用、無用者略過」的原則。
組合語言只是所有平台組合語言的統稱。不同平台擁有不同的指令集與機制(如 x86、ARM、MIPS 等)。文中所指的「某種」,特指你日常工作平台所對應的組合語言。
反對掌握組合語言的聲音,大致歸納為六點:
反方觀點核心圍繞「利益、收入、興趣」三點,它們交織難分。確實,許多高職位、高收入工程師不懂底層,但這不代表他們無能,反而往往極具能力。這看似與我支持學習組合語言衝突,但我認為「追求」一詞可化解矛盾:追求可指向任何領域、方向、目的與標準,故掌握與否本無對錯。以下分享我作為程式設計師的真實感受。
進入行業多從編程開發起步,初衷多源於對編程的濃厚興趣——它驅使我們熬夜、鑽研、進步。對 C/C++ 程式設計師而言,興趣佔據極大權重。試舉幾個具體例子:
這本書極其細緻優美,闡述 C++ 物件模型的實例與理論。但在具體編譯器與平台下,你是否產生過更深疑問?
this 指標如何傳入成員函數?成員函數、普通函數、靜態成員函數有何異同?__cdecl、__stdcall、__thiscall、__fastcall 等調用慣例,本質區別與實現機制為何?int b = a > 0 ? 100 : 200; 編譯器會有何優化?是否存在比較跳轉?int a = 10; 在 VC 開啟全域優化後是否仍存在?如何從本質論證?float a = 100; int b = a / 30; 背後是否隱藏函數調用?調用何函數?為何?__declspec(thread) int g_nNum = 0; 你知道 g_nNum++; 的具體實現機制?這些疑問若你身為熱愛編程的 C/C++ 程式設計師,定想一探究竟。上層開發確應關注功能與產品,但我深信:本著技術、熱愛與自我技術成長,向下理解底層,能極大增強上層開發的通透度與全局掌控力。親身經驗:掌握關鍵細節與全局設計後,任何問題都能迅速反應、追查、處理。雖然現代編譯器極強大,細節可交由其優化,但編譯器非萬能,人才是最智能的。掌握非必然,但掌握了會更好。
許多初學者乃至工作數年的程式設計師,停留在 C/C++ 語法層面,用得心應手,問及本質卻語塞。我個人經歷表明:掌握語法後,向下關注語法背後的具體實現,認知會豁然開朗——在記憶體、資料、程式底層運行機制上建立深刻認知。這如同去海邊玩耍,若不潛水看海底世界,便錯失許多精彩,而這些精彩正是程式設計師應有的追求之一。
對 Java、C#、Web 領域程式設計師,組合語言似較遙遠,關注度較低。但同樣作為「讓程式在機器上跑起來」的角色,底層疑問可作為興趣研究,目的同樣是讓自己更通透、更熟悉平台。「通透」難以言傳,我個人感受是:能從現象聯繫到本質實現,並從本質勾勒出清晰生動的心智圖像,一切盡收眼底,有種居高臨下、望長城內外的寬廣感觸。
對本身從事底層開發者,掌握組合語言當然是必須。但本文觀點更多源於興趣與通透性。底層工作(特別是破解、逆向)確有枯燥、大量體力勞動,我業餘從事破解逆向數年深有體會。但破解逆向只是領域之一,我做這些多為興趣、為上層提供更本質合理的解釋。上層與底層結合,才是我的根本目的,也是本文想推崇的思路。
綜上,我認為 C/C++ 程式設計師乃至所有程式設計師,無論基於興趣或工作,掌握或了解某種組合語言都有必要,但非強制。需求與追求各異罷了。故不必問別人是否應關注底層、掌握組合語言,答案已然明顯。
號外:若想了解更多掌握組合語言的好處,可參閱本部落格「C/C++ inline 組合語言」版塊文章。