SPARC 彙編/SPARC 指令
以下是對編寫 SPARC 程式碼時算術指令格式的快速概覽
- 助記符 %rsrcA, srcB, %rdest
指令助記符(通常但不準確地也稱為“操作碼”)指定要執行的操作型別。rsrcA 是第一個運算元,而 srcB 是第二個運算元。rsrcA 必須是暫存器,srcB 通常可以是帶符號的立即數(13 位)常量或第二個暫存器。rdest 是目標暫存器,並非所有指令都有目標暫存器(例如:cmp 用於比較)。
請注意,在 SPARC 組合語言中,指令始終從左到右讀取。左(如果有的話,還有中間)運算元是源運算元。如果操作將結果寫入任何位置(幾乎所有操作都會這樣做),則結果將寫入最右邊的運算元(目標暫存器或目標記憶體位置)。
在 SPARC 組合語言中,以下指令完全有效
add %r3, %r4, %r5
add %r3, 16, %r5
- 第一條指令將暫存器 3 和暫存器 4 相加,並將結果放在暫存器 5 中。
- 第二條指令將暫存器 3 和數字 16 相加,並將結果放在暫存器 5 中。
如您所見,SPARC 彙編在每個暫存器名稱之前放置一個 % 符號,而數字文字則以普通方式寫入。
警告:此語法與英特爾語法(在 PPC 晶片和一些編譯器中使用)相反。
還應注意,許多 SPARC 指令(例如邏輯和算術指令)都有每個指令的版本,在助記符末尾附加了“cc”。這些指令執行與其非“cc”對應指令相同的功能,但還會設定條件程式碼(稍後會詳細介紹),這些條件程式碼可用於在程式中控制分支。例如,上面提到的“add”指令有一個對應指令“addcc”,當執行加法時,它會設定特定的條件程式碼,這些條件程式碼會在後面的分支指令檢查這些程式碼時決定是否要分支到程式的另一個部分。
註釋不會被編譯器讀取,並且用感嘆號表示。感嘆號之後的該行上的任何內容都將被忽略。註釋有助於您理解自己在做什麼以及為什麼要這樣做。以下是一個註釋的糟糕示例
sub %l0, %l3, %g1 ! Subtract local register 3 from l0, and put the result in global 1. ! add %g1, %l4, %g1! We should add in local 4, but I'm not doing that yet
我們可以輕鬆地知道我們在做什麼;程式碼說明了這一點。註釋沒有告訴我們任何資訊。
但是,這更好
sub %l0, %l3, %g1 ! Subtract our monthly expenses from our monthly income.
! This will later be used in function _foo.
! add %g1, %l4, %g1! Local 4 will hold "other" sources of income, but we're not there yet.
現在我們知道我們在做什麼(我們在計算這個月的零錢),以及為什麼要這樣做(函式 foo 顯然會使用這個)。此外,請注意這兩個示例中的第二行都不會執行,因為它們的指令已被註釋掉(顯然是為了以後實現)。
請注意,許多人在彙編程式碼中幾乎註釋每一行程式碼,因為有時在沒有像變數名稱、複雜結構等有用內容的情況下,很難判斷髮生了什麼。
標籤透過在程式碼中的某個位置放置“label_name:”來表示。由於標籤只是為編譯器提供地址的區域,因此它們可以用於直接儲存在程式中的任何內容:最常用的是,它們用於函式跳轉(透過分支或呼叫語句),或引用常量變數的方法。如果它是函式而不是跳轉,則必須在它之前放置“.global”。就像每種語言一樣,有一個特殊的標籤/全域性,那就是“main”標籤,程式從這裡開始。
.global main
main: save %sp, -64, %sp
mov 5, %l0
cmp %l0, 5
be,a end
ta 1 ! Should NEVER happen
end: mov 1, %g1
ta 0
在這個程式中,有很多東西可能無法理解,但這是一個完整的程式。它從主函式開始(由“.global main”定義,後面跟著標籤)。然後它將值“5”複製到本地暫存器中,然後將該暫存器與值“5”進行比較。如果它們相等,它會分支到標籤 end,程式然後退出。