[英]Mips-Assembly beq and
我有一個關於 Mips 條件語句的問題。我可以在 beq 中使用 and 運算符嗎? 例如在 C 我可以寫 if(arr[0]=='a' && arr[1]=='b' && arr[2]=='c') 但是我怎么能在 mips 程序集中寫這樣的代碼?
從根本上說,我們將控制流與我們正在測試的條件的邏輯相結合。 正如@Jester 告訴你的那樣,我們可以在 C 中執行/觀察這一點,這對於這些轉換通常比組裝更友好。
你可以看到:
if(arr[0]=='a' && arr[1]=='b' && arr[2]=='c') {... }
相當於:
if (arr[0]=='a') {
if (arr[1] == 'b') {
if (arr[2] == 'c') {
...
}
}
}
所以,如果你知道怎么做if (x == y) {... }
那么只需應用 3 次。
在匯編語言中,我們唯一的決策控制流結構是“if-goto”,當然只能測試簡單的條件。
因此,要執行if (x==y) { then-part } else { else-part }
,使用“if-goto”樣式,我們測試x==y
並且在該條件為假時,我們圍繞then-part
和else-part
。 由於我們在條件 false 上進行分支,因此當條件為真時,我們無法分支並運行我們在條件測試之后立即編寫的then-part
。
由於我們在條件 false 上進行分支,因此出於所有實際目的,我們在 C 中以“if-goto”樣式編寫: if (x;=y) goto ElseLabel;
然后是then-part
翻譯......
供參考,請參閱以下帖子:
不, beq
需要 2 個寄存器並比較它們,僅此而已。 請記住,匯編語言反映了機器代碼在一條指令中可以做什么。 做更復雜的事情通常需要更多的指令。
要將&&
多個條件放在一起,您需要
多個beq
和/或bne
指令; 一串樹枝
或在一個寄存器中創建一個值,該值表示分支前多個條件的邏輯和。 例如,加載所有 3 個字節並分別用'a'
、 'b'
和'c'
對它們進行xori
處理。 (為匹配產生0
)。 然后or
將這些結果放在一起,看看最終結果是否為0
( bne
或beq
針對$zero
)如果是,則 3 個字節中的任何一個都沒有不匹配的位,因此條件為真。
第二種方式優化了 C 邏輯具有的短路評估。 請注意,在 C 表達式中,如果a[0] != 'a'
甚至不會訪問a[1]
,因此即使a
是指向頁面最后一個字節的指針,它也不會出錯,並且下一個頁面未映射。 (假設a[0] == 0
或其他東西,一個空的以 0 結尾的字符串)。
但是,如果您確實知道可以安全地訪問字符串/數組的所有 3 個字節,那么這是一個選項。
當條件類似於if (x < 5 && y < 10)
時,它作為優化更容易/更有效,您可以使用 2x slti
指令實現以比較寄存器,並將這些 regs 放在一起,然后beq $t0, $zero, skip_if_body
在這種檢查 3 個連續字節的特殊情況下,它基本上是memcmp(a, "abc", 3)
。
如果你知道a
是字對齊的,你可以做一個字加載來得到你想要的 3 個字節,加上一個我們需要忽略的垃圾字節。
MARS 模擬了一個 little-endian MIPS 系統,所以我們想要的 3 個字節是單詞中的 3 個最低有效字節。 (一般來說,MIPS 可以按大端或小端運行。)
# assuming a[] is a word-aligned static array
# and little-endian MIPS
lw $t0, a # pseudo-instruction for lui / lw to construct the full address
li $t1, 'abc' << 8 # 0x63626100 if your assemble doesn't like multi-char literals
sll $t0, $t0, 8 # shift out the 4th byte which we need to ignore
bne $t0, $t1, skip_if_body
# if body: a[0] == 'a' && a[1] == 'b' && a[2] == 'c'
...
skip_if_body:
...
jr $ra
如果a
實際上是已知字對齊的寄存器中的指針,您當然也可以使用它。 lw $t0, ($a0)
。
我將不需要的字節從負載中移出,而不是用 AND 屏蔽它,因為andi
無法編碼0x00FFFFFF
。
如果不知道a
是對齊的,則可能需要使用未對齊負載的lwl
/ lwr
。
或者如果我們有 2 字節 alignment,則lhu
+ lbu
分別加載 16 位和 8 位; 如果我們仍然想合並一個分支,我們可以使用xori
一次檢查 16 位,利用立即數的全寬。 或者只是使用li
/ beq
。
在寄存器中構造'abc' << 8
需要 2 條指令( lui + addiu
或ori
)
不,您只需執行兩個beq
指令來考慮這兩種情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.