為了操作系統,再一次看匯編語言(王爽,第三版),匯編這東西說着說着就到硬件了,類似於群雄割據,反正再出個什么協議或者規范什么的太晚了...
我挺喜歡這樣的,偶爾看看大神吵架簡直就是人生一大樂趣,當然不管咋樣,我就打個醬油,為自己做做筆記,說道做筆記,在學校的習慣,做筆記就是全篇復制,沒有自己的思想,抓不住重點,這種習慣也讓我多次放棄了寫博客的習慣,關鍵不是寫博客,做筆記,而是逼迫自己去思考,置於烤到了什么...who cares
=================================
王爽〔匯編語言〕教程批判(轉)
我在百度貼吧里面, 驚訝地發現有學生正在編寫"B800直接寫屏"的程序作為練習. 這種落后於時代達30年之久的技術, 怎么會有學校教授呢? 隨后我發現, 這些程序居然來源於清華大學王爽教授的[匯編語言]教程第二版. 於是我感到好奇: 為什么王爽選擇了這樣一些落后於時代達30年之久的技術進行傳授.
我下載了王爽的[匯編語言]第二版. 我的第一感覺, 這本書既然講到了"B800直接寫屏"技術, 它應該產生於1985年左右的時代. 然而我卻驚訝地發現: 這本教程竟然寫作於2008年! 王爽教授應該更新他的知識圖譜. 2008年的CPU市場的情形究竟是怎樣呢? 8086退出市場已經有20年了, 市面上已經不再有純粹意義上的8086, 只有使用硬件模擬8086指令的機器. 這種硬件模擬跟軟件模擬是沒有什么實質區別的, 你在手機上也可以模擬8086的硬件動作, 只不過手機上是ARM指令集, 所以只能軟件模擬, 並不能硬件模擬, 效率比硬件模擬低了12倍, 對於教學用的只有幾十行的匯編代碼而言, 根本看不出有什么差別. 你選擇一個, 已經退出市場達20年的CPU的匯編語言作為教材, 到底是什么意思呢?
然后我們檢查你的選用依據, 發現你解釋為"常用而又結構簡潔", 喔噻! 你知道"常用"這句話是什么意思嗎?
我 來告訴你什么叫"常用": 你家里面有一台桌面電腦吧? 你的桌面電腦有一個鍵盤吧? 這個鍵盤里面所使用的CPU是8047. 你為什么不認為, 8047是"常用"的CPU呢? 你究竟是根據什么來定義這個"常用"呢? 你的鍵盤里面有一個CPU, 你的鼠標里面也有一個CPU, 你的主板上面有一個CPU風扇, 那個控制CPU風扇的器件也是一個CPU, 你的顯卡有一個風扇, 那個控制顯卡風扇的器件也是一個CPU; 你的機箱里面有一個電源, 那個電源里面也有一個CPU - 真正常用的CPU是單片機的CPU, 你為什么沒有選擇某種單片機的CPU來進行講解呢?
你 的第二個選用依據是"結構簡潔". 喔噻! 你難道不知道8086是 CISC機器嗎? 第一次聽到有人說, CISC機器結構簡潔. 你是根據什么來做出這一判斷的呢? 與什么來做比較呢? 與Z80來做比較嗎? Z80是4個寄存器的寄存器組, 8086也是4個寄存器, 它們的復雜度似乎相當啊! 與ARM來做比較嗎? ARM是16個寄存器的寄存器組, 8086僅僅只有4個寄存器, 你是根據這一點來判斷8086"結構簡潔"對嗎? 在你眼里, 寄存器組越小, 結構就越簡潔對吧?
從硬件結構的角度來說, 8086是 CISC機器, 有一個極其龐大的指令集, 龐大的指令集同時即意味着龐大的譯碼機構, 所以8086的硬件結構非常的復雜, 別的不說, 首先譯碼機構就很復雜; 從軟件結構的角度上來說, 8086有着豐富的尋址方式, 而RISC機器(比如ARM)則是 Load/Store 模式, 只有少數幾種尋址方式, 軟件結構更為簡潔. 事實上, Intel公司從未說過自己的CPU結構簡潔, 從來都是吹噓自己的CPU功能強大. 功能強大即意味着結構復雜, 無論從想象的角度還是事實上, 都是如此.
王爽教授之所以認為8086結構簡潔, 實際上是受到了流行因素的影響. 8086系列是桌面系統的主流CPU, 占有90%的市場, 於是王爽教授把自己的眼光局限在8086系列上面, 並且僅僅只在8086, 80286, 80386, 80486, 80586, 80686之間進行比較, 然后認為8086比較簡單, 於是就選擇了8086, 然后就把8086的這種簡單, 說成是簡潔.
8086遠遠談不上簡潔, 相反, 它是邏輯上最為復雜的系統, 並且這種復雜是一種不必要的復雜. 8086機器是一種16位機器, 機器字長的限制, 使得8086難以尋址超過64K的地址. 為了解決這一問題, 8086引進了一種邏輯上非常丑陋的體系架構, 即CS, DS, ES段寄存器. 不可否認的是, 這種臨時性的解決方案, 獲得了巨大的成功,並且使得8086成為了最暢銷的16位CPU, 然而, 一旦發展出32位的機器, 這種解決方案的必要性, 也就消失了. 我問你: 在當代的計算機生產序列里面, 有依舊使用中的8位CPU, 比如你電腦鍵盤里面的8047, 有依舊使用着的32位CPU, 比如手機和桌面電腦里面的主CPU, 但是16位的CPU在哪里? 它已經從生產序列中消失了, 對吧? 它只是一種臨時性的解決方案, 作為一種過渡形態, 存在了短暫的時間, 然后消失於歷史長河. 之前沒有它的影子, 因為人們還沒有能力制造它, 之后也沒有它的影子, 因為人們已經不再需要它, 它就是一種歷史過渡, 等歷史渡過了那個時刻, 它就只有消失的份.
當代程序員從不顯式地操作CS, DS, ES段寄存器, 他們僅僅簡單地設置為平板(flat)模式, 然后操作其它的設備. 然而真實的Windows操作系統從不真正工作在平板模式, 而是使用這些程序員所從不使用的CS, DS, ES段寄存器, 去實現一些非常復雜的高級功能. 你的學生從參加工作的第一天起, 直到退休的那個時候, 從未對CS, DS, ES段寄存器進行過任何一次顯式操作, Windows系統也不允許他們對於段寄存器進行操作. 一旦他們操作了這些段寄存器, Windows會終止程序的運行, 並且認為, 這一程序存在有某種異常.
既然你的學生, 一輩子都不會操作CS, DS, ES段寄存器, 難道你不認為, 有必要略去針對CS, DS, ES的任何介紹嗎? 而, 一旦略去了對於CS, DS, ES的任何介紹, 你難道不認為, 80386實際上, 比8086更為簡單嗎? 8086本來就是一種過渡形態, 為了克服16位的局限, 它不必要地復雜. 你把這種不必要的復雜, 引進了[匯編語言]教程里面.
一旦你把8086匯編語言, 改為80386匯編語言, 你會發現: 你的整個[匯編語言]教程, 可以省略好幾個章節. 既然你選擇了, 並不去介紹完整的8086指令集, 你當然也可以選擇, 並不介紹80386里面的CS, DS, ES段寄存器. 反正你的學生, 一輩子也用不上(除非他去做操作系統, 那種機會很少的). 這樣一來, 你的整個[匯編語言]教程, 將會多余好幾個課時, 可以考慮, 到底應該增加些什么內容.
首先我們來考慮, 傳統CPU到底是什么樣子. 傳統CPU, 大致上由 ALU, 寄存器組, 譯碼部件, 取指部件這幾大部分所組成. 其中譯碼部件和取指部件被認為是"軟件透明的". 從軟件的角度, 看不見針對這些部件的操作, 雖然實際上, 它們確實操作着這些部件. 比如說你執行 jmp Label_1; 的時候, 你實際上操作了取指部件, 但是軟件看不見這種操作, 軟件看見的僅僅是, 程序的執行跳到了 Lable_1 所在的地址. 既然軟件看不見, 就可以視作不存在. 所以, 從軟件的角度來說, 傳統CPU是由[ALU + 寄存器組]所組成的架構, 還有一些附屬的配件, 主要是IO和中斷.
當代CPU遠比傳統CPU復雜, 主要包括幾個方面:
1. 傳統CPU, [ALU + 寄存器組]架構;
2. 協處理器部件: 浮點協處理器(80387), MMX/SSE;
3. 高速緩存部件(Cache);
4. 存儲體管理單元(MMU);
5. 多核架構部件(SMP).
其中MMU和SMP主要是由操作系統管理的. 你的學生里面, 只有極少數, 畢業后會加入操作系統公司, 那些公司都有專門的培訓, 所以, 這些內容都沒有必要在大學課堂上講授.
浮點協處理器(80387)通常是由編譯器自動處理, 你的學生里面, 也只有極少數會加入編譯器公司, 它們也有培訓, 所以也沒有必要介紹.
Cache在80386和80486里面都是透明的, 后來雖然提供了有限的操作可能, 但是主要是由操作系統管理, 所以也沒必要介紹.
所以, 可以考慮增加的課程為: MMX/SSE.
再考慮到, 匯編語言的傳統應用場景有兩個:
1. 再單片機編程里面, 使用匯編語言, 直接操作硬件.
2. 在高級語言編程中, 專門針對某些額外影響性能的關鍵函數, 使用匯編語言改寫, 進行代碼優化.
使 用匯編語言直接操作硬件方面, 由於單片機領域已經發展出了一種專用的C語言, 稱作C51, 這種專用的C語言, 特別適合於直接操作硬件. 所以, 使用匯編語言直接操作硬件的應用場景已經大為縮小. 所以, 當代匯編語言最主要的應用場景就是代碼優化, 尤其使用MMX/SSE所進行的代碼優化. 所以, 應該考慮增加MMX/SSE的講解和應用實例.