1. 程式人生 > >5.1 設計暫存器機器

5.1 設計暫存器機器

5.1 設計暫存器機器
為了設計一個暫存器機器,我們必須設計它的資料路徑(暫存器和操作)
和序列化這些操作的控制器。為了演示一個簡單的暫存器機器的設計,
讓我們看一看尤拉的演算法,就是用於計算兩個整數的最大公約數的。
正如我們在1.2.5部分看到的那樣,尤拉演算法能被用一個迭代的流程執行。
如下面的程式:

(define (gcd a b)
   (if (= b 0)
     a
    (gcd b (remainder a b))))

一個機器執行這個演算法,必須有A和B這兩個輸入值,所以讓我們假定這些數儲存於有這些名稱的
暫存器中。基本的操作有檢測暫存器B的值是否是0,和計算 暫存器A的值除以暫存器B的值得到
的餘數。計算餘數的操作是一個複雜的流程,但是暫時假定我們有一個原生的裝置用於計算餘數。
在求最大公約數的每一輪計算中,暫存器A的內容必須被替換成暫存器B的內容,暫存器B的內容
必須被替換成暫存器A的舊的內容除以暫存器B的舊的內容的餘數。如果這些替換能同時進行,
就方便了,在我們的暫存器機器的模型中,我們假定在一個步驟中,僅有一個暫存器被允許賦一個
新值 。為了完成替換的操作 ,我們的機器使用了第三個暫存器,我們稱為T的臨時暫存器。(首先,
餘數被放在T,然後,B的內容放在了A,最後,放在T中的餘數被放在了B。

通過使用在圖5.1中顯示的資料路徑圖,我們能夠演示這個機器需要的暫存器和操作。
在這個圖中,暫存器A,B,T 用矩形表示。每一次向一個暫存器賦一個值時都被顯示成一個箭頭
後面跟著一個X,從資料的源,指向暫存器。我們能夠認為X是一個按鈕,當它被按的時候,
允許資料值從它的源頭流向設定好的暫存器。按鈕旁邊的標籤是我們引用按鈕時的名稱。
這個名是隨意的,並且能被寫成有意義的值(例如,A<-B的含義是按了按鈕後,把暫存器B的
內容賦給暫存器A)。對於暫存器的資料的源可能是另一個暫存器(在A<-B的賦值中),
也可能是一個操作的結果值(在T<-R的賦值中) 或者是一個常數(一個內嵌的值,不能被改變的值,
在資料路徑圖中被表示為一個三角形包含著一個常數)。

從常數與暫存器的內容來計算值的操作在資料路徑圖中,被表示為一個包含著操作的名稱的梯形。
例如,在圖5.1中,一個標識為REM的盒子表示的是一個操作,用來計算暫存器A,B的值的餘數。
沒有按鈕的箭頭從輸入的暫存器和常數指向這個盒子,並且用箭頭把操作的輸出值指向了目標暫存器。
一個測試被表示成一個包含著測試名稱的圓圈。例如,我們的求最大公約數的機器,有一個測試暫存器
B的內容是否是零的操作。一個測試也有從輸入暫存器和常數來的箭頭,但它沒有輸出的箭頭,
它的值能被控制器使用,而不是資料路徑。總之,資料路徑圖顯示了機器所需要的暫存器和操作和
它們必須被如何地連線起來。如果我們把箭頭視作電線,X按鈕視作開關,那麼資料路徑圖就
非常像能用電子元件組裝起來的機器的電路圖。

為了資料路徑能夠實際地計算最大公約數,所有的按鈕必須被按照正確的順序依次按下。
用圖5.2中的控制器圖來描述這種序列。控制器圖的元素顯示出資料路徑的元件應該被如何地操作。
在控制器圖中的矩形框標識著資料路徑中的按鈕被按下,箭頭描述了從一個步驟到下一個步驟的序列。
在控制器圖中的菱形框則表示一個判斷條件。最終執行這兩個序列箭頭中的哪一個,取決於
在菱形框中標識的資料路徑的測試的值。我們能夠用物理上的類似現象對控制器進行解釋:
可以把控制器的圖想象成一個有彈子在遊蕩的迷宮。當彈子滾入一個盒子,它就按到了按鈕上。
當彈子滾到一個條件結點時,它離開結點的路徑取決於測試條件的結果。把資料路徑與控制器圖結合起來
就完整地描述了計算最大公約數的機器。我們啟動控制器(滾動起來的彈子)在標識為開始的地方,
然後把資料放在暫存器A和B中。 當控制器到達了終點時,我們將在暫存器A中找到最大公約數的值。

練習5.1  設計一個暫存器機器,來計算斐波那些數,使用由如下的程式指定的迭代的演算法,
並且為這個機器 ,畫出資料路徑圖和控制圖。

(define (factorial n)
    (define (fact-iter product counter )
     (if (> counter   n)
               product
 (fact-iter  (* counter product)
            (+ counter 1)
   )
     )
   )
   (fact-iter 1 1))