2016-12-18 51 views
1

我具有其中我要解釋關於以下MIPS彙編代碼一些事情的分配:MIPS大會,雷0x1001

.data 
x: .word 4711 
y: .word 10 
z: .word 0x0A91 
e: .word 0 

.text 
.globl main 
main: 
lw $2, x 
lw $3, y 
lw $4, z 
add $2, $2, $3 
sub $3, $2, $4 
sw $3, e 
li $2, 10 
syscall 

第一指令lw $2, x組裝時被分離成兩個指令。說明是lui $1, 0x00001001,然後是lw $2, 0x00000000($1)。據我所知,lui將十六進制值1001移動到寄存器的上半部分,此時存儲在$ 1中的值爲0x10010000,但我不明白1001的來源以及第二條指令的含義。我真的會在這個問題上得到任何幫助。我正在使用MARS來組裝和運行這個程序。

+0

'0x10010000'恰好是x'的'地址。 – Jester

+0

哦OK – Max

回答

2

MIPS指令的長度是32位,程序使用的地址也是如此。
這意味着lw指令無法將完整的32位地址指定爲立即數。 簡而言之,指令lw $t, var無效(預計極少數情況下)。

事實上,它的編碼是

lw $t, offset($s) 
1000 11ss ssst tttt iiii iiii iiii iiii 

比特表明,只有16比特被用於指定一個地址(以及必須指定一個基址寄存器,最終$zero寄存器可以使用)。

所以彙編程序這招:每當你使用lw $t, var它組裝該指令到2個指令,一個地址的高16位加載到$at和使用$at作爲基址寄存器與一個lw將地址的低16位作爲偏移量。

lui $at, ADDR_H   #ADDR_H is ADDR >> 16 
lw $t, ADDR_L($at)   #ADDR_L is ADDR & 0xffff 

注意,由於從lw + $atADDR_L讀取中使用的最終地址是ADDR_H < < 16 + ADDR_L = ADDR。如預期。

有微妙這裏,指出了Mike Spivey(非常感謝他),請參閱下面

這種指示,不直接映射到ISA,被稱爲僞指令$at寄存器是爲彙編器保留的,用於實現它們。


在MARS可以通過取消選中設置禁用僞指令>通行許可證擴展(僞)指令和格式
雖然沒有僞指令的編程將會非常快速地變得令人討厭,但完全理解MIPS架構至少應該做一次。


Mike Spivey正確地指出的是,16位偏移立即是符號擴展被添加到基址寄存器之前
這需要修正我稱爲ADDR_H的值,以防ADDR_L在解釋爲16位二進制補碼時變爲負值。
如果結果爲真,則ADDR_H必須遞增。
ADDR_H的通式可被校正到ADDR_H = ADDR >> 16 + ADDR[15]其中ADDR[15]表示比特的ADDR 15的值(這是ADDR_L符號位。

+0

一個小錯誤:lw指令中的偏移量是帶符號的,所以用一個移位單獨計算ADDR_H是不正確的,如果ADDR_L變爲負值,那麼ADDR_H需要增加1來補償。 –

+0

@MikeSpivey非常感謝!這是一個非常好的觀點!我相信只要將原始地址的bit15添加到ADDR_H就可以解決問題,我正在編輯答案 –

+0

當寫一個MIPS彙編,我把 短ADDR_L =(short)ADDR; short ADDR_H =(ADDR - ADDR_L)>> 16; assert(ADDR == ADDR_H << 16 + ADDR_L); 這相當於同樣的事情。 –