學習筆記:指令格式 (Computer Science 9645)

歡迎進入機器碼的世界!

你好!這一章是你理解電腦核心運作的關鍵。我們將超越像 Python 這樣的高級程式語言,深入了解中央處理器(CPU)真正能讀懂的原始語言:機器碼 (Machine Code)。別擔心,這聽起來可能很複雜,但我們會拆解每個電腦指令的藍圖:指令格式 (Instruction Format)

理解指令格式至關重要,因為它解釋了:

  • 像「將 5 加到暫存器 R1」這樣簡單的指令是如何翻譯成一系列位元(bits)的。
  • 電腦如何知道「執行什麼操作」以及「在哪裡找到所需的數據」。

第一部分:處理器指令集 (Processor Instruction Set)

當你撰寫程式時,CPU 需要確切知道它可以執行哪些動作。這份有效動作的清單稱為處理器指令集 (Processor Instruction Set)

什麼是指令集?

指令集是特定 CPU 能夠理解並執行的所有指令(命令)的完整集合。你可以把它想像成 CPU 的字典和詞彙表。

  • 從基本的算術運算(加、減)到記憶體存取(載入、儲存),每個指令都在這個集合中定義。
處理器的專有性

非常重要的一點是,指令集是處理器專有的 (processor specific)。這意味著:

  • Intel CPU(許多桌上型電腦所使用)使用的指令,與 ARM CPU(常見於智慧型手機)使用的指令是不同的。
  • 如果你使用處理器 A 的指令集編寫程式,它通常無法直接在處理器 B 上執行,除非處理器 B 被設計為能模擬(emulate)處理器 A。

重點總結:CPU 的語言(指令集)對於該類型的處理器來說是獨一無二的。


第二部分:指令的剖析

每一個指令(無論是機器碼還是組合語言)都遵循特定的格式。它必須包含三個基本組成部分:

  1. 運算碼 (Opcode / Operation Code)
  2. 定址模式 (Addressing Mode)
  3. 運算元 (Operand(s))

比喻:食譜指令
你可以把一個指令想像成食譜中的一個步驟:

攪拌 (Mix) (運算碼),直接 (Directly) (定址模式) 使用 標示為『材料』的碗 (bowl labeled 'Ingredients') (運算元) 中的內容。」

1. 運算碼 (Opcode - Operation Code)

運算碼告訴 CPU 要做什麼操作。

  • 它是指令的功能,例如 ADD(加)、SUBTRACT(減)、LOAD(載入)或 STORE(儲存)。
  • 在機器碼中,運算碼由特定的位元模式表示(例如,0010 可能代表 ADD)。

2. 運算元 (Operand(s))

運算元指定指令應該對什麼數據進行操作,或者去哪裡找這些數據。

運算元可以是以下三者之一:

  • 數值 (Value)(數據本身,例如數字 5)。
  • 記憶體位址 (Memory Address)(RAM 中的某個位置)。
  • 暫存器 (Register)(CPU 內部的一個小型高速儲存位置)。

3. 定址模式 (Addressing Mode)

定址模式告訴 CPU 如何解讀運算元——運算元是指數據本身,還是一個位置?

機器碼指令的格式(位元的佈局與大小)會根據指令類型而有很大差異(例如,一個簡單的 HALT 停止指令可能只需要運算碼,而複雜的計算則需要運算碼、定址模式和多個運算元)。

快速複習:指令藍圖

指令 = 運算碼(做什麼)+ 定址模式(如何找到數據)+ 運算元(數據或位置)。


第三部分:指令的表示方式

我們需要兩種方式來表示指令:一種給機器看,一種給我們人類看。

機器碼 (Machine Code / Binary)

在其原始形式中,機器碼完全以二進制 (binary)(0 和 1 的序列)表示。

  • 這是最低級的語言;可以直接由 CPU 執行。
  • 範例:0010 0101 00001010(這可能代表:ADD,立即定址,數值 10)。

組合語言 (Assembly Language / Mnemonics)

組合語言使用助記符 (mnemonics)——即短小、人類可讀的代碼——來代表機器碼指令。

  • 對於程式設計師來說,助記符比冗長的二進制字串更容易閱讀和編寫。
  • 範例:ADD #10, R5

你知道嗎?CPU 無法直接理解助記符。它們必須由一種稱為組譯器 (Assembler) 的軟體翻譯成二進制的機器碼。

重點總結:機器碼是二進制(0s/1s);組合語言使用助記符(如 ADD, LOAD, STORE)。


第四部分:理解定址模式(關鍵!)

定址模式決定了 CPU 如何解讀運算元欄位以找到所需的數據。課程大綱要求你理解並應用三種主要類型。

1. 立即定址 (Immediate Addressing)

在立即定址中,運算元欄位就是實際的數值 (data),直接供指令使用。

比喻:冰箱上的便條紙
如果你告訴某人:「數值是 5」,你不需要告訴他們去哪裡找,因為你已經直接給了他們這個數值。

  • 運作方式:指令本身直接包含了數值。
  • 用途:將常數或立即數載入暫存器。
  • 範例 (組合語言):LOAD #5, R1(將數值 5 載入暫存器 R1)。「#」符號通常表示立即定址。
立即定址小撇步:尋找常數值。數據就在那裡,可以「立即」取得。

2. 直接定址 (Direct Addressing)

在直接定址中,運算元欄位就是位址 (address/location),可以在該處找到數據。

比喻:信箱編號
如果你告訴某人:「去 100 號位址找那個數值」,他們必須前往位置 100 才能取出物品。

  • 運作方式:CPU 將運算元解讀為主記憶體位址暫存器編號。然後它會前往該位置提取數據。
  • 用途:存取儲存在記憶體中的變數。
  • 範例 (組合語言):LOAD 100, R1(將儲存在記憶體位址 100 的值載入暫存器 R1)。
常見錯誤警示:不要將位址(位置)與數據(位置內的內容)搞混。在直接定址中,運算元「就是」位址。

3. 間接定址 (Indirect Addressing)

在間接定址中,運算元欄位指定一個暫存器,而該暫存器儲存了主記憶體中數據的實際位址

這是一個兩步驟的過程:

  1. 查看運算元以找到暫存器編號 (R_X)。
  2. 前往 R_X 找到記憶體位址 (A)。
  3. 前往記憶體位址 (A) 找到實際數據。

比喻:索引卡片
有人告訴你:「看看那個信封(暫存器 R1)。信封裡面有一張紙,上面寫著『位址 500』。現在去位址 500 找那個物品。」

  • 運作方式:運算元指向一個暫存器,該暫存器間接地指向所需的記憶體位置。
  • 用途:對於遍歷陣列或複雜的資料結構非常有用,因為儲存位址的暫存器可以輕鬆地進行遞增(增加)。
  • 範例 (組合語言):LOAD (R2), R1(括號表示間接定址。將儲存在暫存器 R2 內的記憶體位址中所對應的值,載入到暫存器 R1 中)。

定址模式比較

模式 運算元包含... 獲取數據的步驟
立即定址 數值本身 0 步(數據直接提供)
直接定址 數據的位址(在記憶體或暫存器中) 1 步(直接前往該位址)
間接定址 一個儲存數據位址的暫存器 2 步(先去暫存器,再去記憶體位址)

重點總結:掌握這三種定址模式(立即、直接、間接)對於理解指令如何定位數據至關重要。