overview contents show-all home
#+TITLE:  構架 / architecture
#+AUTHOR: 謝宇恆 / XIE Yuheng

* 費恩曼的比喻
** 來源
   * 本節內容來自 費恩曼 關於計算機架的演講
     原始演講的視頻 :
     ><><>< computers-from-the-inside-out.mov
   * 我看見 費恩曼 (richard feynman)
     用一個比喻來 介紹電子計算機的構架
     我覺得非常有趣
     所以
     我們嘗試來重新敘述
     並且仔細觀察一下這個比喻
   * 費恩曼 有一系列的關於
     heuristic 和 idiosyncratic thinking
     的見解
     我認爲 其中的很多觀點都非常值得我們學習
** 正名
   * 計算機的形態各式各樣
     多因其輸入輸出設備不同而產生
     對輸入和輸出設備的設計和想像可以天馬行空
   * 輸入過程和輸出過程之間的是計算過程
     各種需要被輸入的信息
     被輸入設備數字化
     然後傳遞給計算機去計算
     所得到的數字化的結果
     被輸出設備轉化成需要被輸出的信息
     #+begin_src return-stack
     (天馬行空的輸入)
     [ 數字化的信息 ]
        (((處理)))
     [ 數字化的結果 ]
     (天馬行空的輸出)
     #+end_src
   * 而當談論計算機的構架時
     我們談論的重點就是中間這個計算部分
     而不是 計算機外觀
     也不是 計算機獲取輸入信息的方式
     也不是 計算機展示輸出信息的方式
     如果把計算機比作人的話
     我們只講這個人用以思考的器官
     即他的大腦
** 檔案館
   * 檔案館有很多抽屜
     每個抽屜上有一個地址
     每個抽屜裏可以存放多張卡片
     
     drawer.jpg

** 檔案館員工一名
   * 給這個員工配備了一個黑板
     用於計算時打草稿
     
     worker.jpg

** 推銷員的卡片
   * 有一些抽屜用來存放 公司的推銷員的卡片
     每個銷售員一個抽屜
   * 每個銷售員每個月新增一張卡片
   * 卡片上記錄
     1. 名字
     2. 地址
     3. 固定工資
     4. 提成比率
     5. 銷售額
** 合計支付金額
   * 比如老版來給檔案館員工說
     合計本月應該支付給廣州的銷售員的金額
     我們來構擬一下 檔案館員工 的工作流程
   * 何如
*** 答
    * 找黑板上的一塊地方 寫上零
      作爲累加器
    * 遍歷整個檔案館中
      存放公司的推銷員的卡片的所有抽屜
      算出需要支付的薪金
      薪金 = 固定工資 + (提成比率 * 銷售額)
** 檔案館員工的基本能力
   * 在我們所構擬的檔案館員工的工作流程中
     我們想當然地假設了檔案館員工的很多能力
     我們來仔細觀察一下 都有那些能力
   * 何如
*** 答
    1. 存取卡片
    2. 寫改黑板
    3. 加法
    4. 乘法
** 比喻之形成
   * 何爲 費恩曼的比喻
*** 答
    * 比
      | 能比           | 所比               |
      |----------------+--------------------|
      | 檔案館         | 一級存儲器 (內存)  |
      | 檔案館員工一名 | 中央處理器 (CPU)   |
      | 黑板           | 中央處理器的寄存器 |
    * 他所能做的操作是
      1. 從某個抽屜中拿出一張卡來
         把其中的值記錄在草稿黑板上
         #+begin_src fasm
            mov rax, [address]
         =對應於=>
            mov 黑板上的某個位置, [某個抽屜中的某張卡片]
         #+end_src
      2. 用草稿紙做計算
         #+begin_src fasm
         在黑板上做計算
            add rbx, rcx
            add rbx, 8

         參照抽屜中的卡片做計算
            add rbx, [address]
         #+end_src
      3. 把草稿紙上的值寫回到某個抽屜中的卡片上
         #+begin_src fasm
            mov [address], rax
         =對應於=>
            mov [某個抽屜中的某張卡片], 黑板上的某個位置
         #+end_src
** 小笨
   * 現在有一個新的
     拿卡片 和 放卡片 的速度非常快的人
     [經過測試 其速度是老員工的五倍]
     前來應聘 檔案館員工這個職位
   * 但是在面試的時候我們發現他不會做乘法
     我們很想錄用他
     畢竟他的速度非常快
   * 我想要教會他做乘法
     何如
*** 答
    * 所以我們這樣教他來做乘法
      每當他發現需要將兩個數相稱的時候
      [也許是看到了乘法符號 "*" 也許是 "mul"]
      比如
      | 16 * 32   | 中綴表達式 (infix-notation)   |
      | (* 16 32) | 前綴表達式 (prefix-notation)  |
      | 16 32 *   | 後綴表達式 (postfix-notation) |
      表達形式並不重要 只要讓他能看懂就行
    * 我們告訴他先去看最後兩個數字 "6" 和 "2"
      然後去一個 名字叫 "乘法表" 的抽屜裏
      找第 62 張卡片
      上面寫着 "12"
      顯然
      只要告訴他具體的步驟
      之後他就能按照我們在草稿紙上做乘法的樣子
      去在黑板上做乘法了
    * 也就是說我們發現不必讓他記住 乘法表
      只要讓他知道
      上哪裏去找乘法表中的結果 就行了
      只要讓他能夠
      在看到乘法符號的時候
      能夠按照一系列具體的指令
      存取卡片 並 改寫黑板 就行了
      當然最後他是用加法把乘法的結構算出來的
    * 更重要的一點在於
      我們甚至不必告訴他
      我們嘗試教他做的 是一種叫做乘法的運算
      我們只要讓他能夠
      在看到某個代表指令的符號的時候
      能夠知道應該作出哪樣的一系列操作
      而這一系列操作正是他所擅長的
      即存取卡片
      還有 改寫黑板上的某個地方的值
      僅此而已
    * 也就是說我們可以把乘法定義成
      一系列的簡單的[愚蠢的]存取卡片的操作
      這一系列操作的特點是
      它們遵循非常嚴格的規則
    * 你發現了
      需要記憶的東西[比如乘法表]根本不是問題
      因爲我們的檔案館有很多檔案櫃呢
      而這些檔案櫃的目的正是用來幫助我們記錄東西的
      [也就是內存 也就是電腦的記憶單元]
** 中笨
   * 現在我們又有一個應聘者
     他的速度更快 但是他不會加法
   * 何如
*** 答
    * 我們只要加一個 加法表就行了
** 笨笨
   * 然後又有一個應聘者
     他的速度更快 但是他不知道什麼是數字
     但是他能比較兩個東西是否相同
     也就是說
     他甚至不必知道自己所處理的是數字
   * 何如
*** 答
    * 那麼他的如何獲得我們的指令呢
      指令也寫到一系列卡片上就行了
      我們只要讓他
      按照我們安排好順序的一系列卡片上的指令做事情就行了
    * 那麼現在他的所需要有的能力是什麼
      * 他需要能夠把特殊樣子的卡片和某個指令[某個操作]想對應
      * 他還需要能夠知道指令的順序
        也就是說知道下一個指令的位置就行了
        只要黑板上的一個地方
        寫下用來記錄下一個指令的位置的數字 就行了
        每次開始執行一個指令的時候
        他先給這個卡片上的數字加一
        以讓這個數字所記錄的地址變成下一個指令的地址
    * 你可以發現
      這個笨笨之笨 猶如機器
      而正因如此
      我們其實已經能夠把這些工作機械化了
    * 你可以發現
      如果你能記住很多東西
      那可並不代表你很聰明
      反而很有可能代表你很笨
      笨蛋裏最極端者
      就要屬電腦了
** 大笨
   * 最後的大笨
     所能比較的只是兩個信號
     這兩種信號的屬性並不重要
     可以是 白點 與 黑點
     可以是 0 與 1
     可以是 高頻電磁波 與 低頻電磁波
     可以是 高電壓 與 低電壓
     每一個信號的不同就是一個 bit
     [我們用 bit 這個單位來度量信息]
   * 何如
*** 答
    * 解決方案是
      所有的東西都必須用大笨所能識別的信號來編碼
    * 因爲大笨太笨了
      所以我們先給太笨製作一個抽屜的地圖
      用八個抽屜來舉個例子
      我們發現用三個 bit 就能編碼這八個抽屜
      | 白 白 白 |
      | 白 白 黑 |
      | 白 黑 白 |
      | 白 黑 黑 |
      | 黑 白 白 |
      | 黑 白 黑 |
      | 黑 黑 白 |
      | 黑 黑 黑 |
    * 然後我們可以給他設計一個 "找抽屜的行動準則"
      這裏需要他的一個能力
      即 能夠找到某些抽屜的中間的一個抽屜 就行了
    * 把 白點 與 黑點
      換成 0 與 1
      我們發現我們其實還是在使用數字來給抽屜編碼
      只不過使用的是二進制的數字而已
      | 白 白 白 | 0 0 0 |
      | 白 白 黑 | 0 0 1 |
      | 白 黑 白 | 0 1 0 |
      | 白 黑 黑 | 0 1 1 |
      | 黑 白 白 | 1 0 0 |
      | 黑 白 黑 | 1 0 1 |
      | 黑 黑 白 | 1 1 0 |
      | 黑 黑 黑 | 1 1 1 |
    * 你可以發現數字的集合的重要特點就是其序關係
      | 白 白 白 | 0 0 0 | 000 | 0 |
      | 白 白 黑 | 0 0 1 | 001 | 1 |
      | 白 黑 白 | 0 1 0 | 010 | 2 |
      | 白 黑 黑 | 0 1 1 | 011 | 3 |
      | 黑 白 白 | 1 0 0 | 100 | 4 |
      | 黑 白 黑 | 1 0 1 | 101 | 5 |
      | 黑 黑 白 | 1 1 0 | 110 | 6 |
      | 黑 黑 黑 | 1 1 1 | 111 | 7 |
      這種序關係其實是自然數免費送給我們的
      [副產品 (byproduct)]
      我們並不一定需要
      例如
      可以不用數字的方法是
      就像給人起名字一樣 去給抽屜起名字
      一羣人他們每個人的名字都不同
      這種編碼能夠區分每一個人
      但是人和人之間 並沒有序關係
    * 序關係 是用 後繼關係 來定義的
      後繼關係 比 序關係 更簡單
      後繼關係 是下圖中的 有向邊
      序關係 是下圖中的 有向路
      #+begin_src return-stack
      (0) --> (1) --> (2) --> (3) --> (4) --> > > >
      #+end_src
    * 後繼關係 通常被作爲基本公理 來討論自然數的性質
      比如
      1. 關於 具有序關係的集合 的命題
         通常要用 數學歸納法 來證明
         而數學歸納法 就是 後繼關係 的體現
      2. 加法 乘法 可以用 後繼關係 來定義
         這種定義很適合與用於證明加法乘法某些一般性質
         比如 交換律 和 結合律
    * 而對 加法 乘法 等等運算的實際進行
      不是利用 序關係
      而是利用 對自然數的某種特殊的編碼來實現的
      | 非進位制 | 結繩計數 畫正字 等等 |
      | 進位制   | 二進制 十進制 等等   |
      典型的計算機對加法的實際運算
      就是利用數字的二進制編碼來完成的
    * 把 白點 與 黑點
      換成 高電流 與 低電流
      你可以發現我們已經能夠把這些工作電子化了
    * 甚至把這些東西量子化我們就能得到量子計算機
    * 其實當我們使用匯編語言的時候
      我們並不關心 底層的對構架的實現方式是什麼
      而我們現在所學的
      是一個比喻
      是一個比較抽象模型
      每當需要使用一個特殊的構架的時候
      [比如 x86-64 這個構架 又比如 ARM 這個構架]
      我們把這個比喻具體化就行了
    * 所以我可以說
      就我們學習匯編語言而言
      這個[想像中的]模型已經夠用了
** 編碼
*** ASCII
    * 1 byte
      8 bit
      256 個數字可用與編碼
      其實之使用了
      7 bit
      128 個數字可用與編碼
    * 編碼了基本的英語的大小寫字母
      還有 一些基本的西方的標點符號
    * http://en.wikipedia.org/wiki/ASCII
*** UTF-8
    * unicode
    * 與 ASCII 兼容
      變長編碼
    * http://en.wikipedia.org/wiki/Unicode
      http://en.wikipedia.org/wiki/UTF-8
*** 圖片
    * 字體
      以最古老的圖形接口爲例
    * 顏色
      以 emacs-mode 的語法高亮中使用的顏色爲例
      以 我網頁的源代碼中的 css 爲例
      http://en.wikipedia.org/wiki/RGB_color_model
    * 真正把這些被編碼好的圖片顯示到屏幕上去
      [或者是打印 或者是投影 等等]
      就涉及到了輸入與輸出了
      我們將發現當使用一個操作系統的時候
      跟輸入與輸出有關的細節是被操作系統來處理的
      我們只要使用操作系統所提供給我們的功能就行了
** 編程
   * 寫程序就是去裝填代表指令的卡片到抽屜裏
   * 人們發展出了很多工具來幫助自己寫程序
     比如
     匯編器 編譯器 解釋器
     每一個工具本身也是一個程序
** 總結
* 機器等價性
  * 這就在於 什麼是計算 的問題
  * 這裏形成 了一個術語叫做 Turing 等價
    也就是用我們所描述的這種機器的能力
    來定義什麼是計算
* 機器通用性
  * 我們發現這種構架具有通用性
    給抽屜中填充不同的指令卡片
    我們就能讓機器完成不同的任務
  * 這裏又形成了一個術語
    即 這種構架被稱爲是 Von Neumann 構架
  * 上面我們所描述的只是內存而已
    現在我們添加一個比喻
    即 地下室[磁盤]
    地下室裏可以存放暫時不用的卡片
* 對比喻的批判