你可以幫助我們擴充關於該主題的更多資訊。
本文旨在探討Minecraft中計算系統的設計和實現。
第一章,建造一台計算機,這是一個關於如何在Minecraft中建造計算機以及如何擴展與改進的詳細教學。不需要讀者了解大量的計算機科學方面的知識,因為教學會對其進行解釋,並且會深入研究。
第二章,紅石計算機的規劃,提供了在Minecraft中設計與理解一個紅石計算機的基本概念。不需要讀者了解大量的計算機科學方面的知識,因為教學會對其進行解釋,並且會深入研究。
概述
計算機促進了人們透過編程與其交流的想法的實現。
這篇文章將會為在Minecraft中設計與建造計算機打下基礎,假定讀者相當熟悉傳統紅石電路並且有基本水平的計算機知識。
事實上在不了解計算機是如何工作的情況下是無法建造計算機的。此教學旨在解釋你需要知道的所有內容,但也確實需要一點對計算機科學的了解。涉及的最深層次達到IGCSE[注 1] CS(計算機科學)。
為了在Minecraft中建造計算機能有一個良好的開始,你應該學習計算機科學。有非常多的資源與教學可以用來學習計算機科學,但是推薦觀看Crash Course Computer Science作為入門課程,尤其是1-8節。儘管它不夠透徹,但其內容可以作為你理解計算機的基礎。
在Minecraft中,大多數計算機是由紅石粉,紅石火把以及紅石中繼器組成的,以引起黏性活塞或者紅石燈的變化。它們被一系列的按鈕,控制桿,壓力板等等所控制。另外一些方法(本文沒有涉及)利用了漏斗,礦車或船與紅石。
應用
計算機與計算器的區別在於計算器在沒有使用者輸入時無法連續執行複雜的指令,而計算機可以連續比較並處理指令來完成任務。計算機可以被用在很多方面,從創造一個智慧房屋到執行一張冒險地圖。但是,由於Minecraft對於計算機的限制(將會在後文說明),它們仍然只是個抽象概念,但也是理解CPU結構與嵌入式系統的良好工具。
由於Minecraft中的紅石計算機非常慢並且臃腫,很難為它們找到實際應用。即使是最快的紅石計算機也要花數秒來完成一次計算,還有著數千方塊大的體積。因為指令方塊的速度快且有著清晰且高級的指令,所以它們相比於紅石計算機有很大的優勢。
有一些Mod可以改變計算機的速度,比如TickrateChanger能改變遊戲刻速率。
計算機的基礎功能
計算機具有以下能力:
- 從有地址的記憶體中讀寫;
- 可以對記憶體的狀態進行比較,並據此執行操作,包含了重寫記憶體;
- 可以基於寫在記憶體中的內容執行一個功能。我們把這樣的內容叫作「程式+資料」,並將其編寫為程式。
一個值得注意的例子是最基本的計算機概念,即圖靈機,它能從一條無窮長的編碼和指令中讀取資訊,以完成一個功能。
在Minecraft中設計和建造圖靈機是可以實現的。然而,由於我們要設計更基本的一些東西,所以我們不討論這個。
計算機的部件
一個現代計算機有五個基礎部件。為了保證正常執行,並透過執行計算來處理資料,這些部件是必不可少的。
計算機的五個組成部分
- 運算單元(ALU)(這不是必需的,但通常存在)
- 執行加減乘除(也有的計算機有例如移位的功能);
- 透過邏輯門進行布林運算。
- 控制單元(CU)
- 執行接收到的指令;
- 控制其他單元。
- 資料儲存器(Data Memory)
- 儲存與返回資料。
- 指令儲存器(Instruction Memory)
- 返回指令,並發送到CU;
- 可以被設定,但不需要向資料儲存器那樣頻繁。
- 在馮諾依曼結構下是不必須的(指令將會和資料儲存在一起)
- 輸入/輸出裝置(I/O)
- 允許計算機與玩家和世界互動;
- 可以將資訊輸入到計算機(按下按鈕,或透過日光感測器);
- 可以從計算機中輸出資訊(透過紅石燈、音階盒等)。
第一章 建造一台計算機
介紹與條件
紅石的邏輯緊密地反映了二進位邏輯,即紅石元件可以是啟動或非啟動的,可以被解釋為0或1。在本教學中,我們將提到基礎的二進位邏輯與眾多簡單的計算機科學術語。這裡有一篇文章,很好地解釋了二進位以及如何轉化到二進位。請讀計算機的結構一節,因為接下來我們對於計算機的設計是基於此的。
這一章會關注於知識的運用與紅石的操作,以來創造一台簡單的8位元計算機,並且會解釋如何建造以及它是如何工作的。
所有的內容被分為了理論與實踐兩部分。理論部分會深入解釋會發生什麼,而實踐部分會說明如何在Minecraft中建造,它應該是什麼樣子,可能會提供存檔。
- 我們將要建造的計算機(MASIC計算機)
- 步驟1:記憶體和地址解碼器(理論) (未完成)
- 步驟1:記憶體和地址解碼器(實踐)
- 步驟2:構建算術邏輯單元(理論)
- 步驟2:構建算術邏輯單元(實踐) (未完成)
- 步驟3:指令集和機器結構(理論)
- 步驟3:指令集和機器結構(實踐) (未完成)
MASIC計算機
我們將在本教學中製作的計算機擁有8比特、16位元組的記憶體。我們將要製作的輸入輸出系統是一個七段的數字顯示器(以顯示十六進位數字)和一個控制面板。
MASIC計算機旨在成為一種適合所有人的計算機,並且不專門從事一項任務,因此它可以透過讀取其自己的記憶體進行完全編程(在第7節:指令集中進行了說明)。簡單的I/O(輸入/輸出)非常適合多種用途,並且儲存器大小足夠。它以相當快的速度執行(由於其體積小)。
步驟1:記憶體和地址解碼器(理論)
解碼器將二進位的數字轉換成十進位。例如,看著8位元解碼器,00點亮代表0的第一個燈,01點亮代表1的第二個燈,10點亮代表2的第三個燈,11點亮代表3的最後一個燈。
步驟1:記憶體和地址解碼器(實踐)
地址解碼器
0000 0000(注意第一條輸出已亮起)
0000 0001(注意第二條輸出已亮起)
0000 0010
0000 0011
這是我們要構建的地址解碼器的設計。
上面是一個簡單的2位狀態,因此它有兩個輸入(透過左右中繼器)。輸出是在圖片最上方的紅石線,當所有條件滿足時會關閉。狀態是紅石訊號輸入是否會關閉上面的紅石線; 如果是,則狀態為紅石輸入。在上面例子中,必須是左側輸入為OFF(0),右側輸入為ON(1),才能關閉頂部的紅石線。因此,它期望的狀態為(OFF,ON)(即二進位01)。
這裡,顏色為藍色的方塊應設為ON(1),以便停止啟動頂部的紅石線。一旦每一位都停止啟動紅石線,紅石線就會關閉。
這些基本上是每條輸入用一個或兩個非門,多條匯入到一個或門,然後用非門後輸出。
上面是一個8位元狀態,它期望8個輸入的順序正好是0000 1101。紅石火把正好按照0000 1101的順序放置,所以我們看到頂部的紅石線熄滅。
現在,如果將它們中的多個放在一起,我們就可以用藍色位以二進位數進行計數,以獲得8位元的所有255個狀態。下面的一個是8位元,並具有四個狀態期望。查看右側的圖像以查看實際效果。現在,每個綠色輸出可以是一個儲存單元,如果我們繼續以二進位進行計數,它將計到255。
輸入為0000 0011(紅石火把為輸入),藍色位與目前狀態匹配時,綠色輸出為ON。
- 0000 0000 - 第一個訊號輸出(在右側的圖像上)
- 0000 0001 - 第二個訊號輸出
- 0000 0010 - 第三個訊號輸出
- 0000 0011 - 第四個訊號輸出
因此,現在我們繼續以二進位數進行計數,直到數到0000 1111並停止。現在我們應該有24(16)個狀態期望值,這就說明我們完成了地址解碼器。由於指令集的局限性,我們不會繼續計數到1111 1111。
步驟2:構建算術邏輯單元(理論)
算術邏輯單元(ALU)會比較並執行二進位數的數學運算,並將結果與控制單元(CU,即計算機的中心組件)進行互動。本來也應與CPU互動,但它將與計算機本身一樣大。許多教學都希望讀者首先構建ALU,因此該主題在網上被廣泛涉及。
我們將要構建的ALU可以在兩個輸入上執行四個重要操作,並返回正確的輸出。A,B均為8位元輸入。
- A + B(A加上B)
- A >>(右移一位,與二進位除以2相同)
- << A(左移一位,與二進位乘以2相同)
- 非A(將A每位取反)
由於某些程式需要大量操作才能執行,因此計算機內部還可以有多個ALU,這些操作不依賴於先前的操作,因此可以進行執行緒化。 所以將它們委派給不同的ALU可以顯著提高該程式的速度。
二進位加法器
兩個數字相加
在一個加法單元中,對於每個位(對於我們的計算機,我們需要四個,因此需要4位)都要有一個全加器。全加器將接收三個輸入,每個輸入可以是1或0。前兩個將是使用者的輸入,第三個將是「進位」輸入。「進位」輸入是上一個全加器的輸出,稍後將對此進行說明。全加器將輸出兩個結果:首先是輸出,然後是「進位」輸出,該輸出作為輸入發送到下一個全加器中,占一個位。 例如,希望將數字0101和1011相加。第一個全加器將把第一位的值1和1作為它們的兩個輸入(我們從右到左閱讀)。由於這是第一次加法計算,因此沒有「進位」輸入。全加器將把1和1相加;它是0,並將進位的1送到下一個全加器的進位輸入。下一個全加器將把0和1相加,進位輸入為1。因此將0、1和1相加,得0,並且下一個進位輸入為1。重新回顧二進位加法,應該能解決疑惑。
全加器
為了執行加法運算,所有ALU都需要多個全加器。每兩位送入一個全加器,所有全加器互相連接,產生的輸出是兩個字節的和。每個全加器具有一個輸入、一個輸出、一個進位輸入和一個進位輸出,就像人執行9 + 1或01 + 01的加法操作一樣。全加器由幾個邏輯門構成,這可以透過二進位的命名法實現。 教學/算術邏輯給出了全加器和半加器的非常詳細的介紹,目前,有一個構造方法的示意圖。它提供四個輸入/輸出,應與其他加法器連接以建立一個單元。對於此示例,我們將在四位計算機中將四個加法器連接在一起,以便我們可以將所有四個位都取為輸出。第一個加法器將缺少輸入進位,這是因為之前的位(第一位)沒有任何進位。輸入進位將保持為零。第四加法器還將缺少輸出進位,並且由於我們只能支持四個位,因此將忽略該輸出。附加的第四個進位輸出連接到溢出標誌,表示無法完成該操作。這稱為二進位溢出。
因此,基本上,進入Minecraft並構建一個完整的二進位加法器(如圖所示)並將其連接起來。應該有八個輸入和輸出。嘗試將控制桿和紅石燈分別放在兩端以測試。因此0010 + 0011應該算出0101(2 + 3 = 5,我們從右往左讀)。
分數數字
計算機透過浮點算術的形式處理小數,僅在較大位計算機(16-64位元)和需要使用小數的計算機中有用。浮點運算或高精度算法可以實現此目的。另一種更簡單但效率較低的方法是為所有數字分配2的一個冪,以使它們和選定的2的冪「相乘」。玩家必須對每個數字都執行此操作,並假設單位1是您選擇的2的冪的1倍。例如5 = 1012,因此5 × 23 = 1010002,即5(1012)向左移動了3位(1010002)。因此,現在,新系統中的值為1 × 23 = 10002,這將為0.12、0.012或0.0012留下表示方法;0.012 × 23 = 102。這將導致您的計算機設定更為複雜。
兩個數字相減
一個全部帶正負符號的加法器(加減混合計算元件)
數字減法非常簡單。ALU首先必須變更第二個數字(即減數),將其從正數轉換為負數。一個數取負,對應的二進位補碼是反轉原二進位數補碼(0變為1,1變為0)後再加1。
示例:10減去9
| 1. 0000 1001 | (9的二進位補碼,我們希望將它轉換為-9) |
| 2. 1111 0110 | (將9取反,所有0變為1,1變為0) |
| 3. 1111 0111 | (加1,這是-9的二進位補碼) |
| 4. 0000 1010 | (10的二進位補碼) |
| + 1111 0111 | (加上-9的二進位補碼) |
| ---- | |
| 0000 0001 | 結果(10 +(-9)= 1)(存在溢出,這僅意味著結果不是負數) |
這帶來了帶符號數字的複雜性,但這是二進位數的作用,用來將其指定為正數或負數。結果是負數還是正數由溢出標誌確定。如果有溢出,則表示數字為正,否則為負。
為實現這一功能,可以讓ALU做3個操作。 實現A減B的操作是:A SUB B
- NOT B (將B的每一位取反)
- B ADD 1 (將B自加1)
- A ADD B (將A加B的值存到A)
- RETURN A (A即為回傳值)
兩個數字相乘
乘法是重複的加法,因此最簡單(但效率低下)是將A多次加到變數B上。
這是它的偽機代碼:
操作:A * B
- C = 0
- (set C to) C ADD A (將C+A的值存入C)
- (set B to) B SUB 1 (將B自身減1)
- JUMP IF (B > 0) TO LINE 2 (如果B>0,回到第2行繼續執行)
- RETURN C (C為回傳值)
但是,有更高效的方法做乘法。一個好方法是將第一個數字重複位移到第二個數字中每個1的位置,然後求和。
下標2表示二進位,粗體表示十進位。
| 操作 | 說明 | ||||||
|---|---|---|---|---|---|---|---|
| 1 | 1 | 代表3,注意有2個1 | |||||
| × | 1 | 0 | 1 | 1 | 代表11 | ||
| 1 | 1 | 將112左移0位,因為二進位數10112的第1位是12 | |||||
| + | 1 | 1 | 0 | 將112左移1位,因為二進位數10112的第2位是12 | |||
| + | 1 | 1 | 0 | 0 | 0 | 將112左移3位,因為二進位數10112的第4位是12 | |
| 二進位數10112的第3位是02,因此不用加 | |||||||
| 1 | 0 | 0 | 0 | 0 | 1 | 結果為33 | |
因此這對更大的數操作起來更高效。
操作:A * B
- C = 0
- D = 0
- JUMP IF (BIT (D) OF B == 0) TO LINE 5 (如果B的第D+1位是0,則跳到第5行)
- (Set C to) C ADD A (將C+A的值存入C)
- (Set D to) D ADD 1 (將D自加1)
- (Set A to) << A (將A左移1位)
- JUMP IF (D < LENGTH OF B) TO LINE 3 (如果D比B的位數小,即沒有超出,則跳到第3行)
- RETURN C (C即為回傳值)
不要忘記:
<< A (左移1位)等價於A * 2
>> A (右移1位)等價於A / 2
假如這些數字是唯一確定的或者CPU必須做大量的相似數字處理,可以考慮使用一個可查的窮舉表來頻繁調用乘法。因此,在極端情況下,你可以透過硬編碼的方式來得到答案。
步驟2:構建算術邏輯單元(實踐)
步驟3:指令集和機器結構(理論)
詳細說明在第2章:指令集。我們可以建立自己的一套。
對於我們正在建造的MASIC計算機,有一個8位元的系統,所以這意味著在堆棧記憶體的每個插槽上的每條指令都是8位元。堆棧記憶體是儲存任何資訊並儲存在RAM中的記憶體。所以將會有一個計數器,稱為程式計數器,它每週期遞增1次。循環是指CPU取得指令,解碼指令(找出該指令是做什麼的)和執行指令(執行它讓它做的事情)。然後,透過遞增程式計數器並在堆棧記憶體中讀取位於該位置的資訊,移動到下一個記憶體地址。
因此,堆棧記憶體中的每個字節都有8位元供我們使用。有些指令需要一個地址,比如將記憶體載入到寄存器中,這樣我們就可以對其執行操作。每條指令將被分成兩部分,每部分4位。第一種是類型,類型將指定計算機必須做什麼;地址將是我們將執行操作的值所在位置。
操作碼/操作數
憑藉這個4位資料組,我們可以有24種操作碼,即代表16種不同的操作。我們的電腦將有兩個寄存器,所以因此操作碼的一位用於指定操作將在其上執行的寄存器,並在下文用x表示。
指令與記憶體將被放在同一位置,由於指令的地址部分只有四位,我們只能從1-16行引用記憶體,需要一些巧妙的編程來適應更大的程式。每個程式的記憶體也限制為16位元組。值和指令本質上是相同的,因此,如果您編寫一條指令將其儲存到先前儲存指令的行上,這將有效地用一個值覆蓋該指令。
意外執行值是一個問題,因此必須設定並使用STOP指令來防止任何錯誤。這需要理解的東西太多了,所以自己去找找基礎教學吧。另外,不要忘記為您的IGCSE同時使用用戶端/伺服器端和資訊通信技術。
必要條件
本節將介紹計算機中常見的簡單主題和組件。 看懂下文你需要:看懂計算機的部件和第2章中的資訊及第3章中的概念,如ALU、RAM、寄存器和二進位操作。
MASIC指令集
因為這裡的計算機是指令集的草稿,只有基本要素。這是基於其他彙編語言的,但經過變更以適應我們的體系結構。有兩個寄存器,所以我們需要指令在兩個寄存器上執行操作。
| 二進位碼 | 操作碼 | 效果注釋 |
|---|---|---|
| 0000 | LOAD R1 | 將地址載入到寄存器1中 |
| 0001 | STORE R1 | 將寄存器1的內容儲存到該地址中 |
| 0010 | JUMP R1 IF | 如果寄存器1的值為0,則跳到地址一行 |
| 0011 | ADD R1 | 將地址處的內容加入到寄存器1 |
| 0100 | <<R1 | 在寄存器1中向左移位 |
| 0101 | NOT R1 | 按位非寄存器1(對寄存器1按位取反) |
| 0110 | JUMP OPERAND | 跳到第OPERAND行 |
| 0111 | STOP | 終止程式 |
| 1000 | LOAD R2 | 將地址載入到寄存器2中 |
| 1001 | STORE R2 | 將寄存器1的內容儲存到該地址中 |
| 1010 | JUMP R2 IF | 如果寄存器2的值為0,則跳到地址一行 |
| 1011 | ADD R2 | 將地址處的內容加入到寄存器1 |
| 1100 | <<R2 | 在寄存器2中向左移位 |
| 1101 | NOT R2 | 按位非寄存器2(對寄存器2按位取反) |
| 1110 | OUT R1 | 輸出寄存器1 |
| 1111 | OUT R2 | 輸出寄存器2 |
解釋:
1000 0011表示將地址3的數載入到R2寄存器,因為1000為載入到寄存器2中,0011為3。
這些可以在一個過程中進行,以便可以執行功能。
編寫程式
下面這個程式能計算斐波那契數列:(0,1,1,2,3,5,8……)
| 地址 | 二進位指令 | 實際指令 | 注釋 |
|---|---|---|---|
| 0 | 0000 1110 | LOAD R1 14 | 將寄存器1設定為地址14的值 |
| 1 | 1000 1111 | LOAD R2 15 | 將寄存器2設定為地址15的值 |
| 2 | 1011 1110 | ADD R2 14 | 將地址14的值加入R2 |
| 3 | 1110 0000 | OUT R1 | 輸出寄存器1 |
| 4 | 0001 1111 | STORE R1 15 | 將其放入地址15 |
| 5 | 1111 0000 | OUT R2 | 輸出寄存器2 |
| 6 | 1001 1110 | STORE R1 14 | 將其放入地址14 |
| 7 | 0110 0000 | JUMP 0 | 回到地址0,重複執行 |
| ... | |||
| 14 | 0000 0001 | 1 | |
| 15 | 0000 0001 | 1 |
前面是低級彙編語言的一個例子。如果它是用高級語言編寫的,比如C++,它看起來更像是這樣:
#include <iostream>
using namespace std;
int main()
{
int n, t1 = 0, t2 = 1, nextTerm = 0;
cout << "Enter the number of terms: ";
cin >> n;
cout << "Fibonacci Series: ";
for (int i = 1; i <= n; ++i)
{
// Prints the first two terms.
if (i == 1)
{
cout << t1 << " ";
continue;
}
if (i == 2)
{
cout << t2 << " ";
continue;
}
nextTerm = t1 + t2;
t1 = t2;
t2 = nextTerm;
cout << nextTerm << " ";
}
return 0;
}
指令週期
圓角矩形為元件,矩形為不同單元,綠色箭頭為路線
指令集是低級彙編語言,所以我們希望將它更多地集成到硬體裡。這圍繞著「取得→解碼→執行」循環(見上)在執行。 在CPU中,有4個重要寄存器:
- 程式計數器(PC)跟蹤計算機目前執行到哪裡;
- 儲存地址寄存器(MAR)跟蹤下一個記憶體地址的位置;
- 儲存資料寄存器(MDR)跟蹤目前內存在哪一個位置;
- 現行指令寄存器(CIR)跟蹤哪條指令正在被執行;
- ALU累加器(ACC)跟蹤ALU的輸入和輸出。
還有四個組件需要記住:地址解碼器、記憶體、指令解碼器和ALU。
- 取得(Fetch)
程式會獲得下一條指令。
- PC將指令碼發送到MAR;
- PC自己增加1,為下一條指令做準備;
- 地址解碼器將地址解碼,並從記憶體中取得相應地址中的資訊;
- MDR接收到需要的資訊。(在這個圖片的例子中,如果MAR為0001,MDR會接收到「LOAD R1 1」,即將地址1的資料載入到寄存器R1中)
- 解碼(Decode)
程式會識別取得的是什麼指令。
- CIR透過資訊流,從MDR中接收到資訊;
- 指令解碼器將指令解碼,知道接下來要做什麼。
- 執行(Execute)
程式會執行這條指令。
- 在本圖片例子中,程式接收到「LOAD R1 1」這條指令,指令解碼器將這條指令拆分為操作碼和操作對象。操作碼是「LOAD R1」,操作對象是「1」。
- 操作對象被送到MAR,以便取得對應地址的資訊。
- MDR接收到那個地址的資訊。(在這個例子中,是同一行)
取決於指令,有四種情況可能發生。
- 如果指令是加(ADD),ACC就會被要求從資訊流中取得資訊,ALU會對其執行操作,再次輸出到ACC。
- 如果指令是載入(LOAD),控制單元(CU)會將指令載入到寄存器中。
- 如果指令是儲存(STORE),CU會將指定位置的值設定(SET)為記憶體中MAR指定的值。
- 如果指令是輸出(OUT),CU會將指令送到外部輸出裝置。
- 重複(Repeat)
指令週期會重複進行,直到執行到停止(STOP)指令,或是用完記憶體。
步驟3:指令集和機器結構(實踐)
第二章 紅石計算機的規劃
在Minecraft中,為了讓你的紅石計算機最適合你手頭的任務,需要有以下三個主要的設計目標。而有些得失需要進行考慮,比如當計算機的規模更大時,執行就會更慢,因為中繼器的數量會隨著距離的增加而增加。越多的記憶體,意味著速度就越慢,體積越大。
- 緊湊程度
這台計算機的規模有多小?在Minecraft中,設計一台生存模式的計算機很大可能會強調這一點。所需的重複次數將隨著大小的增加而增加。
- 記憶體大小
它能容納多少的記憶體?它可以計算多少數字和字節?這對於大規模的計算機來說是很重要的,如那些可以完成更複雜算法和更大規模指令集的計算機(例如說,計算平方根或是三角學)記憶體大小或者位體系結構越大,計算機越複雜。
- 速度/效能
它能以多快的速度執行操作呢?它是否達到了最大最佳化的程度以執行工作呢?使用客製化設計構建一個計算機可以將更多的任務和分配給硬體,從而大大地提升計算機的效能。這在現實世界中的某些超級計算機中表現得很明顯,這些超級計算機可以非常高效地進行一些操作。Minecraft中的紅石計算機速度是非常慢的,一些模組,例如TickrateChanger可以變更Minecraft遊戲用戶端的遊戲刻速度,以提高計算機速度。
紅石計算機可以像真實計算機一樣運作,遵循計算機設計和硬體架構中的原則。有幾個關鍵的設計決策會影響架構;你對計算機預期的大小和功能應該在構建部件之前具體確定。建造紅石計算機需要理解這四個概念,並考慮最合適的方法,這對計算機是最實用的。
一些事情需要考慮:
- 執行模型(記憶體的計算機組織與程式儲存和執行)
- 字節大小(資訊的大小,你的紅石計算機用這些執行指令)
- 指令集(紅石計算機的一個結構)
- 記憶體大小(資料可以儲存在記憶體中,可儲存資料多少取決於記憶體大小)
有一個這裡確定的選擇將在你的計算機各種組件的設計中提供強有力的指導。
我們會在本章最後一節應用這些內容並計劃構建CPU。這個CPU會在下一章建造。
執行模型
在記憶體中儲存指令塊的技術叫做程式,允許計算機同時執行各種不同的任務。由計算機來儲存和檢索這些程式使用的裝置是計算機的執行模型。世界上最成功的兩種執行模型,哈佛和馮·諾依曼,幾乎在今天可用的100%的計算機上執行。
哈佛結構
哈佛結構物理分離檢索組成活躍程式的指令的裝置和程式在執行期間訪問的資料訪問器。
為使用哈佛結構的電腦編寫的程式執行訪問主存總線的任務最多可能快100%。但是要注意,哈佛結構的某些記憶電路體積會很大。
馮·諾依曼結構
馮·諾依曼結構使用一個兩步的過程來執行指令。首先,載入包含下一個指令的記憶體,然後載入的新指令執行時被允許訪問相同的記憶體,使用同一個記憶體的程式和資料推動元編程技術,像編譯器和自修改代碼。
馮·諾依曼體系結構是第一個提出的計算模型,幾乎所有現實中的計算機都使用馮·諾依曼結構。
位數大小
位數大小是計算機物理尺寸的主要因素。 在Minecraft中,從1位一直到32位元的機器已經被成功構建出來。 常見的位數大小的組合:
| 資料 | 指令 |
|---|---|
| 4 | 8 |
| 8 | 8 |
| 8 | 16 |
| 16 | 16 |
資料字
計算機在任何特定時間可以操作的資訊量被計算機的資料字大小代表了。
在數字二進位中,計算機的資料字大小(以位為單位)等於計算機主總線中通道的寬度或數目。
資料字通常表示整數,即編碼為二進位數字模式的整數。
二進位整數編碼可表示的最大容量是2資料字所占位數 - 1。
比如,有8位元資料字大小的計算機在總線上有八個通道(一組導線和連接部件),因此,最多能計算到28 - 1 = 255。8位元模式下計算超過255的數字是不可能的,因為計算255 + 1會帶來額外的一個進位,這需要第9個位才能儲存,於是發生了二進位溢出。最後結果返回一個不正確的0。
這個過程可以用下表形象描述:
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 255 | ||
| + | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | |
| = | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
一些常見的整數資料大小是:
| 最大可表示的數量 | 所需的位數 |
|---|---|
| 1 = 21 - 1 | 1 |
| 7 = 23 - 1 | 3 |
| 15 = 24 - 1 | 4 |
| 255 = 28 - 1 | 8 |
| 65535 = 216 - 1 | 16 |
| 4294967295 = 232 - 1 | 32 |
資料字大小還決定了可以由計算機的ALU(算術和邏輯單元)處理的數字的最大大小。
指令字
計算機完成一條指令所需的資料量被計算機指令字大小代表。
計算機的指令字大小通常是其資料字大小的倍數,這有助於在程式執行期間檢索指令時最小化儲存偏移。
指令集
這裡是一系列指令,控制單元(CU)能將它們解碼,然後執行。
指令是計算機執行的基本功能。一些例子包括:
- 加、減、乘和除
- 從RAM/ROM/三級儲存器中讀寫資料
- 從RAM中載入和卸載資料
- 分支到代碼的其他部分
- 與寄存器比較
- 選擇一個邏輯運算(與非、或非、非……)
指令可以被編碼進RAM,從ROM中讀取,或直接被控制桿或按鈕啟動。每條指令都有自己指定的二進位字串(例如,0000可以代表從寄存器中讀取資料,0001代表A與B相加,1011代表將RAM的資料儲存到三級寄存器,等等),並且可能將自身的二進位編碼轉為十進位(將BIN碼轉為BCD碼),再到十進位解碼器,最後透過總線到ALU或寄存器。
構建CPU
所有的計算機系統都至少有一個處理單元。在執行時,處理單元執行儲存在計算機記憶體中的指令。在計算機內部,有一個中央處理單元(簡稱CPU,不要與CPU內部的控制單元(CU)混淆),在現實生活中,這是一個非常小卻很強大的組件,或多或少地充當計算機的大腦。
在Minecraft中,很難將其壓縮到我們在現實生活中看到的規模,所以如果它看起來像是錯誤的,請不要擔心。
在下一章中,我們將首先設計我們的4位中央處理單元,因為考慮到執行模型(CPU的通信和組織方法),這是我們計算機中最重要的事情,我們可以繪製計算機的構建圖。
CPU的構建圖,基於哈佛執行模型
CPU遵循著一個循環,一共有四個步驟,取得、解碼、執行和儲存來執行指令。CPU首先從RAM取得指令,解碼其含義(指令很可能是一個數字,CPU必須找出它是什麼數字),一旦它理解了指令是什麼,它將執行該操作。有時需要將資料放回儲存器,因此它會儲存資料。然後重複循環。
總線
CPU中共有五條總線,每條總線將資訊從一個組件傳送到下一個組件。總線是連接每個組件的紅石通道。因為我們正在建造一台4位計算機,所以我們的總線只需要四個通道。這些是連接中央處理單元內部組件的紅線和藍線。請注意,藍色總線少於四條線,這是因為它們不攜帶資料。由於總線只能單向傳輸資料(在Minecraft中,雙向中繼器以外的中繼器只能單向工作),所以有兩條總線將中央處理單元連接到外部計算機。
- 資料總線,將輸入/輸出裝置或儲存器資訊與CU連接,以傳輸資訊。指令同樣透過資料總線傳輸。CU也可以透過資料總線傳輸給ALU。ALU不能透過此條總線傳輸,因為它只能單向傳輸。一旦資料由ALU接收,這條線路就會切斷。
- 資料總線,專門用來將ALU的計算資料傳回給CU。同樣地,由於單向傳輸,CU不能將資料透過此線傳輸到ALU。但CU可將資訊傳回到儲存單元,從而變更儲存裝置的值。
- 地址總線,CU透過這條線路傳輸儲存器地址資訊。這就是資訊「居住」的地方。例如,CU請求取得位於地址0001的字節。CU透過地址總線,發送「0001」,接著RAM透過第一條資料總線返回地址裡面的值。需要注意的是,此處的「0001」指的是記憶體中的地址,不是該地址中儲存的值。
- 控制總線,CU透過這條總線與RAM互動。例如,一條線路告訴RAM,將對應字節處的內容設定為CU傳輸過來的值。另一條線路告訴RAM,從CU指定的地址處取得字節資訊。
- 控制總線,連接到ALU,能接收來自ALU的訊號。這些訊號就是標記,可以指示錯誤資訊。比如,CU要求ALU將15和1相加。假設這是一個4位機器,計算15 + 1會得到0,這就是二進位溢出(如上所述)。這時就會有個訊號指示錯誤,ALU會透過這條總線告訴CU。CPU也可以將資料傳送至ALU,讓ALU對那個資料執行另一操作。
部件
控制單元(CU)能從ROM(只讀記憶體)指令中取指令。對於其他計算機來說,這些指令是可以變更的,那就是存到RAM(隨機存取儲存器)中。但是對我們來說,我們要執行一個固定的程式,並不需要變更這些指令。這能大大簡化工程,我們只需要ROM即可。然後控制單元會對指令解碼,通常是將數字轉換成可識別的操作。接著,控制單元執行操作,有時會根據指令要求,透過控制總線將結果存入RAM中。在執行過程中,控制單元也會接收ALU的執行訊號。控制單元也能請求ALU執行操作(比如加減法)。具體互動操作請見上文總線一節。
算術邏輯單元(ALU)會執行控制單元發送的指令,處理二進位數,再將結果告訴控制單元。ALU能執行加法、減法,如果組合起來還能做乘法與整數除法(當然,進一步改造,也可做所有除法)。內部通常是邏輯門,用來處理邏輯值,比如非門、與非門。
現在我們可以選擇一種總線設計,每一種都能達到一開始提到的三種關鍵設計目標,建成Minecraft中的計算機。
第三章 計算機的設計
指令集架構
狀態
儲存器是一系列的位。在Minecraft中,儘管曾經成功創造過32位元和64位元[1]計算機,但是通常情況下儲存器有8位元或16位元。每一位都是兩種可能的狀態中的一種:開或關。而儲存器就是一系列的開和關,用於完成特定的任務。
訊號
現實世界計算機使用二進位,一系列的1和0。「1」表示「開」和「0」表示「關」。在Minecraft中,最好的體現是紅石:有訊號意味著「1」,沒有訊號表示「0」。然而,根據紅石線到儲存器的距離,「0」可以是從0到14的任何訊號強度。你也可以設計,使「1」訊號強度從1到15。
數
我們常規的十進位是一種以10為基數的數字系統。在電腦中使用的數制——二進位,則是以2為基數。為了比較兩者,我們看一下兩位數。在十進位中,左邊的那一位是十位。在二進位中,則是「二位」。比如在十進位中,「10」表示「十」。而在二進位中,「10」表示「二」。有兩種常用的十進位轉二進位的方法:
1. 最高位優先:這種方法需要一點直覺。我們以42為例。首先我們找小於等於42的最大的2的冪(如32 = 25或65536 = 216)。在這個例子中,是32。然後我們用例子中的數字來減它,42-32=10。那麼最左邊的一位就是「1」。隨後我們繼續找下一個2的冪,看它是否小於等於目前的數字。對於這個例子來說,下一個是16,16大於10,所以接下來這一位是「0」。一直找下去直到數字為0為止。無論二的冪是小於還是等於目前的數字,都要減掉它,並且記下一位為「1」。否則下一位就是「0」。用表格來表示這一過程,就是
| 比較 | 計算 | 結果 |
|---|---|---|
| 32<42 | 42-32=10 | 1 |
| 16>10 | 0 | |
| 8<10 | 10-8=2 | 1 |
| 4>2 | 0 | |
| 2=2 | 2-2=0 | 1 |
| 1>0 | 0 |
因此最終42的二進位表示就是「101010」。
2. 最低位優先:這個方法不需要記憶許多2的指數。相反,它重複將數字除以2,使用商作為下一個被除數,餘數作為二進位位。但請記住,此方法從右到左寫入二進位數,而不是像前一種方法一樣從左到右寫入。讓我們重用我們的例子,42:
| 計算 | 餘數 | 說明 |
|---|---|---|
| 42/2=21 | 0 | 最右邊的數字是0 |
| 21/2=10 | 1 | 向左邊一位的數是1 |
| 10/2=5 | 0 | 向左邊一位的數是0 |
| 5/2=2 | 1 | 向左邊一位的數是1 |
| 2/2=1 | 0 | 向左邊一位的數是0 |
| 1/2=0 | 1 | 向左邊一位的數是1 |
商數為0,所以我們停止。 我們同樣得到了二進位數「101010」,與之前相同。
歸類
映射
數字
符號可以用紅石燈或者活塞的推拉方塊產生凸凹顯示:
註:如果用紅石燈的話不要用黃色的方塊做面板,不然不容易分辨。
形式化
變數
變數是數字、字串、字元(套)或布林值(真/假)儲存在RAM中的空間。例如,布林值可以用來儲存程式是否已經達到某種狀態的資訊。一個變數的以下資訊需要儲存:名稱,類型(數字、字串或布林),和變數值。變數,顧名思義,改變。指令操作可以改變變數。在執行程式時建立變數,一旦程式結束,變數值會被從記憶體中刪除。當一個程式重啟,變數會被重設。在Minecraft中也是如此。
語義
資料
資料是計算機處理的資訊,使用二進位表示。
機器架構
算術邏輯單元(簡稱ALU)
ALU是計算機最重要的組件之一,在現實生活和Minecraft中。首先,你必須選擇你希望能夠實現的功能。大多數時候,這些都是加法、減法和一組邏輯選項。
與,或,與非,或者你所喜歡的。你必須建立單位和所有你想要的邏輯門和數學函數和選擇哪一個的輸出顯示。
(資料)總線
用總線允許您的計算機的組件相互通信。
一條總線可以透過使用建立紅石布線連接你的計算機的運算器,隨機儲存器,只讀儲存器,中央處理器和寄存器在一起,這樣他們就可以互相之間發送資料。通常是重要的計劃,建立你的電腦的組件,否則你建立總線過長,或者更糟的是,沒有空間來建立總線,在這種情況下,您可以刪除的組件並重建一個適當的位置,或者使用像WorldEdit移動組件到其他地方。
儲存
在Minecraft或是現實生活中有很多種方式儲存資料。儲存狀態通常為二進位的,非開即關,可透過邏輯運算來執行。
在計算機中,有三種儲存器。要知道,增加硬體的容量亦即增加尺寸,因此每一種儲存器都有自己適合的速度與容量。
主存
主存,也為記憶體,對於CPU來說可以直接且最快訪問。因此,在容量上它也通常很小。
寄存器與標誌寄存器
最快的是儲存在CPU中的記憶體。如下圖,這些是寄存器和標誌寄存器,它們幾乎可以立即設定,並且不需要向其發送任何地址,因為每個寄存器中只能儲存一個字節。
可以切換的紅石位非常大,但可以在2刻內切換。這需要很大的空間,但非常適合快取和寄存器。邏輯門(未顯示)也需要紅石來設定位,如圖中所示,輸入脈衝會導致位翻轉。門會占用更多的空間。寄存器還可以利用鎖定紅石中繼器和精確計時,這將在下面的RAM中解釋。使用計算機時鐘時,可能不需要建立寄存器。當資料在CU或ALU準備處理之前透過線路時,寄存器非常有用。它會將其儲存到寄存器中,並等待CU或ALU執行其功能。
緩衝儲存器
第二快的是緩衝儲存器(快取),將資訊輸入處理器。現實中,它被分為幾個等級,每個等級都有獨立的速度與能力[2]。和寄存器原因相同,它很有用。
隨機存取儲存器
第三快的是隨機存取儲存器(RAM),這比寄存器和快取慢得多,是因為它有地址系統。它與三條總線(資料總線、控制總線和地址總線)連接。資料透過資料總線傳送,無論是設定RAM中資料的值或是從RAM中獲得資訊。控制總線能控制RAM,要「取得」還是「設定」資訊。地址總線能告訴RAM操作的是哪個字節。參見計算機的結構來更加深入了解。RAM非常有用,可以完全替代三級儲存器(是因為它在Minecraft中不易失)。易失的意思是,在現實中,RAM斷電時會丟失所有的資訊,這在Minecraft中不會發生。因此RAM是儲存資訊的極佳方法。
在第一種情況下,RAM使用具有正確定時的鎖定紅石中繼器。這需要一點規劃,但非常節省空間。將總線轉換為多條線路以鎖定紅石中繼器也需要設定定時。這非常耗時,遠遠超過寄存器,但是,它非常緊湊且高效。地址總線(綠色部分)將以二進位方式解鎖某個字節,由控制總線讀取或設定(第二行,左側)。
在大多數情況下,其易失性在Minecraft中不會生效,因此最簡單的方法是使用D觸發器並加入讀寫功能。如下圖所示,它沒有鎖定中繼器,而是使用D觸發器,空間效率更低,但構建更簡單。D觸發器的工作原理或多或少類似於鎖定的紅石中繼器,一個輸入如果打開,將解鎖,直到輸入關閉,另一個將在解鎖後將其設定。輸出可以讀取為一個位,使用與非門可以忽略它或將其放到總線上。這在第一章「建造一台計算機」中有詳細介紹。
二級儲存器
這相當於HDD和SSD。下面介紹一種非常緊湊的儲存技術,要涉及到紅石比較器,能夠儲存高達1KB的實際資料大小。
介紹影片請見此處。
三級儲存器
第三,也是最後一點,是第三級記憶體,它需要大量的時間來讀/寫,犧牲速度但可以儲存大量資訊。在現實世界中,三級儲存器使用的是一種老式的掛載記憶體的機制,而且現在也很少使用了。在Minecraft中,這種系統要用界伏盒來完成,界伏盒中的方塊必須由排序系統進行排序,以表示某種形式的資料。由於這些工作需要大量的紅石比較器和大量的時間,所以讀/寫速度相當慢。然而,利用某些mod可以加快遊戲tick的速度並消除這個問題。這用於儲存長期資料,這些資料需要在程式開始時載入。相當於一台真正的計算機的機械硬碟或固態硬碟。
機器狀態
程式計數器
程式計數器用於告訴CPU應該執行哪行代碼。在每個時鐘週期,解碼器將訪問這個計數器來取得下一個要執行的指令。一些指令會比另一個訪問不同的資料量,或無任何資料,因此解碼器將按由下一個指令確定的量增加程式計數。計數器也被跳轉指令用於控制程式流。
現實中,程式計數器自身並不是一個元器件,只是在其他寄存器旁邊的一個寄存器。然而在Minecraft中,應該建造一個獨立的寄存器,用來儲存程式計數,這並不奇怪。
提示
- 你也可以使用一些像是WorldEdit的模組。
- 如果你在生存模式沒有太多的紅石中繼器,你可以用兩個紅石火把代替。
- 利用顏色進行分區(例如用藍色羊毛建造RAM(隨機存取儲存器),黃色羊毛建造ALU(算術邏輯部件運算器)等)。
- 結構方塊對移動部件、組合多個部件來說很有用。然而,它只能透過指令獲得。
參見
注釋
- ↑ 「International General Certificate of Secondary Education(國際普通中等教育證書)」的簡稱,劍橋全球測試的一部分。
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||










