定址模式

大多数架构的处理器都具有的寻址模式

尋址模式(Addressing modes)是中央處理器(CPU)設計中,指令集架構的一部分。各個指令有不同的尋址模式,這些尋址模式決定此架構下的機器語言指令對應的運算數。尋址模式會通過暫存器中的數值或機器指令中的常數來計算運算數的記憶體位址

在計算機程序設計中,尋址模式主要是匯編語言使用者和編譯器編寫者需要關注的。對於一個相關的概念,請參閱正交指令集,它涉及到任何指令使用任何尋址模式的能力。

警告

注意,各種尋址模式都沒有一個被普遍接受的的名稱。不同的作者和計算機製造商可以為相同的尋址模式賦予不同的名稱,或者為不同的尋址模式賦予相同的名稱。

術語「尋址模式」本身也有不同的解釋:可以解釋為「存儲器地址計算方式」,也可以解釋為「操作數訪問方式」。 在第一種解釋下,不從存儲器讀取或寫入存儲器的指令(例如「將立即數放入寄存器」)被認為沒有「尋址模式」。 第二種解釋允許諸如VAX的機器使用立即數模式位來允許寄存器或立即數。 只有第一種解釋適用於諸如「加載有效地址」之類的指令。

下面列出的尋址模式分為代碼尋址和數據尋址。 大多數計算機體系結構都保持這種區別,但是存在一些允許在(幾乎)任何上下文中使用任何尋址模式使用的體系結構。

下面的說明純粹具有代表性,以說明尋址模式,並不一定反映任何特定計算機使用的助記符。

尋址模式的數量

不同的計算機體系結構在硬件中提供的尋址模式數量上有很大差異。 消除複雜尋址模式並僅使用一個或幾個更簡單的尋址模式有一些好處,即使它需要一些額外的指令,也許還需要一個額外的寄存器。 如果只有一些簡單的尋址模式,那麼設計管流水線CPU將變得更為簡單。

大多數RISC架構只有大約五種簡單的尋址模式,而DECCAX等CISC架構有十幾種尋址模式,其中一些非常複雜。 IBM System/360架構只有三種尋址模式,System/390又添加了一些。

當只有少數尋址模式時,所需的特定尋址模式通常在指令代碼中編碼(例如IBM System/360和後繼者,還有大多數RISC)。 但是當存在許多尋址模式時,通常在指令中留出特定字段來指定尋址模式。 DEC VAX允許幾乎所有指令有多個存儲器操作數,因此保留每個操作數說明符的前幾位以指示該特定操作數的尋址模式。 保持尋址模式指定符位與操作碼操作位分離產生正交指令集 。

即使在具有許多尋址模式的計算機上,實際程序的測量表明下面列出的簡單尋址模式占所有尋址模式的約90%或更多。 由於大多數此類測量基於編譯器從高級語言生成的代碼,因此這在某種程度上反映了所使用的編譯器的局限性。  

對代碼的尋址模式

絕對尋址/直接尋址

   +----+------------------------------+
   |jump|           address            |
   +----+------------------------------+

   (有效PC位址 = address)

絕對尋址指令的有效地址是地址參數本身,無需修改。

PC相對尋址

   +----+------------------------------+
   |jump|           offset             |    相对跳转指令
   +----+------------------------------+

   (有效PC位址 = 下一條指令的位址 + offset,offset 可為負數) 

PC對尋址的有效地址是下一條指令地址加上偏移參數。 通常對該偏移是有符號數,以允許跳轉到指令之前和之後的代碼。

這種尋址方式的跳轉指令特別有用,因為常見的跳轉指令的目標是是附近的指令(在高級語言中,大多數ifwhile語句相當短)。 實際程序的測量表明,對於大約90%的條件跳轉(大約±128或±512字節),8或10位偏移就足夠了。

PC相對尋址的另一個優點是代碼可以是位置無關的 ,即它可以加載到存儲器中的任何地方而無需調整任何地址。

這種尋址模式的某些版本可以是有條件的,這些條件例如兩個寄存器之間的關係:「如果reg1 = reg2跳轉」、一個寄存器自身:「跳轉除非reg1 = 0」或者隱含地狀態寄存器中某些位。

寄存器間接尋址

   +-------+-----+
   |jumpVia| reg |
   +-------+-----+

   (有效PC位址 = 'reg'中的值)

對數據的尋址模式

寄存器(直接)尋址

   +------+-----+-----+-----+
   | mul  | reg1| reg2| reg3|      reg1 := reg2 * reg3;
   +------+-----+-----+-----+

這種「尋址模式」沒有有效地址,在某些計算機上不被認為是尋址模式。

在此示例中,所有操作數都在寄存器中,結果放在寄存器中。

基址加偏移量尋址,及其變種

有時被稱為「偏移尋址」

   +------+-----+-----+----------------+
   | load | reg | base|     offset     |  reg := RAM[base + offset]
   +------+-----+-----+----------------+

   (有效地址 = offset + base 寄存器的内容) 

立即數/字面量尋址

   +------+-----+-----+----------------+
   | add  | reg1| reg2|    constant    |    reg1 := reg2 + constant;
   +------+-----+-----+----------------+

這種「尋址模式」沒有有效地址,並且在某些計算機上不被認為是尋址模式。

常量可以是有符號或無符號的。 例如, move.l #$FEEDABBA, D0將十六進制值「FEEDABBA」值移動到寄存器D0中。

操作數的值保存在指令本身中,而不是使用內存中的操作數。

隱含尋址

隱含尋址模式(在X86匯編語言中也稱為隱式尋址模式)未明確指定源和/或目標的有效地址。

操作碼隱含源(如果有)或目的地有效地址(或有時兩者)。

隱含的尋址在較舊的計算機上很常見(直到20世紀70年代中期)。 這樣的計算機通常只有一個寄存器,可以在其中執行算術-累加器。 這種累加器機器幾乎在每個指令中都隱含地引用了累加器。 例如,操作

a:= b + c;

可以使用序列

load b; add c; store a;

「load」和「add」指令都隱含目的寄存器(累加器); 每個「store」指令都隱含了源寄存器(累加器)。

後來的計算機通常具有多個通用寄存器,它們可以是算術的源寄存器和/或目的寄存器,因此後來的計算機需要一些其他尋址模式來指定算術的源寄存器和目的寄存器。

參考資料