2016-08-16 6 views
0

特にMIPSアセンブリ言語に変換するのに最適ではありません。MIPSアセンブリへの変換配列を使用した言語

これは、元のコードだった:

void swap(int v[], int k, int j) { 
int temp; 
temp = v[k]; 
v[k] = v[j]; 
v[j] = temp; 
} 

我々はこれに得ることができたいくつかの助けを借りて、今私はちょうどまだnoobのをJavaの学習終え、MIPSアセンブリコードにこれを変換する必要があります。どんな助けも歓迎です。

k = k << 2; 
k = k + v 
j = j << 2; 
j = j + v 
temp0 = load(k) 
temp1 = load(j) 
store(k) = temp1 
store(j) = temp0 
+0

は、コンパイラがそれを実装する方法を考えてみて:それはちょうど連続したメモリ空間の束をレイアウトし、最初の1へのポインタを保存します。アドレスを計算するには、オフセットを計算するだけです。インデックス0は0 * 32(0)のオフセット、インデックス1は1 * 32、インデックス2は2 * 32などです(JavaからMIPSアセンブリ言語に比べてCからMIPSアセンブリ言語への移行はずっと簡単です) 。 – EJoshuaS

答えて

0

さて、ここではasmです。 で、上記の疑似コードを前提としていますが、上のHLLに基づいてゼロから書きました。

は、mips ABI準拠である。したがって、引数レジスタを変更(すなわち破棄)することは自由である。したがって、ループで呼び出された場合、呼び出し側は各呼び出しの前にa0-a3を設定する必要があります。

# void 
# swap(int v[],int k,int j) 
# { 
#  int temp; 
# 
#  temp = v[k]; 
#  v[k] = v[j]; 
#  v[j] = temp; 
# } 

# swap -- swap two elements in an array 
# 
# arguments: 
# a0 -- pointer to array 
# a1 -- array index "k" 
# a2 -- array index "j" 
# 
# registers: 
# t0 -- v[k] 
# t1 -- v[j] 
swap: 
    sll  $a1,$a1,2    # k <<= 2 (i.e. byte offset) 
    addu $a1,$a1,$a0    # get address of v[k] 

    sll  $a2,$a2,2    # j <<= 2 (i.e. byte offset) 
    addu $a2,$a2,$a0    # get address of v[j] 

    lw  $t0,0($a1)    # fetch v[k] 
    lw  $t1,0($a2)    # fetch v[j] 

    sw  $t1,0($a1)    # v[k] = v[j] 
    sw  $t0,0($a0)    # v[j] = v[k] 

    jr  $ra      # return 

UPDATE:

私は左シフトのためのsllスタンドを知っています。 adduは何のために立つのですか?

u "接尾辞が" 符号なしの略です。しかし、ではなく、多くの他の場所で使用されているようなです。

[add]の2つのバージョンがあります。 の符号付きのバージョンはaddであり、の符号なしバージョンadduです。それらは両方とも同じ2の補数加算を行うので、同じ結果が得られる。両方正確にはを生成する。

のみ違いは、添加がオーバーフローを起こした場合、addはプロセッサ例外(例えば、「算術オーバーフロー」)を生成することであるが、adduない --itだけラップするであろう。 subおよびアンダーフローと同様です。

たとえば、レジ​​スタ内に0x7FFFFFFFがあり、そのレジスタに1を追加すると、オーバーフローが発生します。あなたは最大値に署名して、あなたがそれに 1を追加し、および出来上がりあなたが最大の署名値(オーバーフローとして知られている、すなわち「飛躍」)にいる始めているためです。

したがって、が正当にのアドレス計算のようにオーバーフロー(32ビットで「ラップ」)する可能性があるものを追加する場合は、符号なしバージョンを使用する方がよいでしょう。

これは、mipsでは、[code/data/stack]プログラムの一部が0x80000000以上で読み込まれる可能性があるためです。

例えば、スタックは0x80001000で開始される可能性がありますし、あなたがそれに十分なデータをプッシュする場合(すなわち$spレジスタがsubで減算されている)、それは最終的に0x80000000の近傍をヒットします。このアドレスの近くでプッシュ/ポップすると、オーバーフロー/アンダーフローが発生します。

これはない間違っている - それは自然であり、そしてあなたがプッシュ操作のためのsubを行う際に、プロセッサが例外を発生させたくないので、あなたはsubuを使用し、[および/または即時命令subiuの形式]。

あなたがまだそれを見つけていないなら、ここにはかなり良い命令セットリファレンス[たくさんの人々が使用しています]:http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.htmlあなたが必要とする可能性が高い指示のほとんどをカバーします。ここで

は、ABIの呼び出し規約の簡単な概要です:http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Mips/altReg.html

+0

こんにちは@CraigEstey、本当にありがとう、あなたは何か新しい毎日を学びます。私が知っているちょうど質問 "sll"は左にシフトの略です。 "addu"は何のために立つのですか? –

+0

'sll'は「shift left logical」を表します。 – babon

関連する問題