![](/img/trans.png)
[英]What's the difference between using ori and addi to initialize a value in MIPS?
[英]What is the difference between an ori operation and an add operation after lui in MIPS?
我想在$t0
存儲3*2^16 + 9
。 我做了lui $t0,3
,我做addi $t0,$t0,3
。 順便說一下,在教科書中,值是通過lui
之后的ori
操作創建的。 我的做法有問題嗎? 兩者有什么區別?
兩者有什么區別?
ori
和addi
允許 16 位立即數。
但是, ori
將零擴展立即數,因此換句話說,立即數始終被視為正數,因此在 32 位中,擴展立即數的高 16 位將為零。
而addi
將對立即數進行符號擴展,因此它被視為 16 位有符號值,可以是正值也可以是負值。
兩者都可以,但是在使用addi
我們必須小心如下:如果低 16 位設置了符號位,那么根據符號擴展和加法的性質,它將產生遞減高位部分的效果,因此需要在上面的立即數上加一個。 例如,假設我們要加載一個常量 0x23458765。 在lui
應給予0x2346不是0x2345,那么addi
得到0×8765,這是否定的,因為直接簽訂16位,因此會減一經提供的0x23460000 lui
,使其0x23458765。
另一個區別是addi
會在溢出時陷入困境,這將是一個非常不受歡迎的副作用。 ori
不會陷入溢出。 但是,我們可以使用addiu
代替,因為這也將溢出不是陷阱,並使用相同的16位有符號立即為addi
。
注意:匯編程序通常會按照您的意圖進行操作,而不是您指定的操作。 使用0×8765與addi
或addiu
在某些匯編器將生成的多個指令,以適應該數目為陽性。 例如,如果你想用 MARS 測試上述序列,我們將不得不使用 -30875 (10)而不是 0x8765 來讓匯編器生成一個立即數 0x8765,否則它將使用多條指令來構建 +34661 (10 ) 。 (使用 -30875 和ori
也會生成多條指令,因此我們必須使用 0x8765 在一條指令中獲得立即數。)
我的做法有問題嗎?
總之,您可以使用任何您喜歡的代碼序列來構建您的常量。 雖然有些文本只會顯示一種方式,但其他文本肯定是可能的,並且沒有“正確”的方式。
話雖如此,但是,如果您使用匯編器偽函數%hi
和%lo
,它們是為與addiu
一起使用而addiu
——這意味着如果低 16 位將顯示為負立即數,則%hi
將執行 +1。 這些函數的用法如下: lui $t0, %hi(label); addiu $t0, $t0, %lo(label)
lui $t0, %hi(label); addiu $t0, $t0, %lo(label)
— 其中label
是(代碼或數據)標簽,但也可以是 32 位常量。 (MARS 不支持這些函數,所以在 MARS 中我們使用li
或la
偽指令代替,它會根據需要生成一兩條指令。)
%hi
和%lo
以這種方式工作的原因是有時序列使用加載(例如lw
)或存儲(例如sw
)而不是addiu
,並且加載和存儲也使用相同的 16 位有符號立即數. (這些序列可以在這里和那里保存一條指令,例如,如果意圖是訪問全局變量。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.