2012-04-18 8 views
0

私はスタックの上にそれらを押し込むことによって4以外の引数を使用するように関数をプログラムしようとしています(私のバージョンのmipsは$ a0- $ a3しかサポートしません)。ここでは、メインの私のコード(抜粋)は次のとおりです。40の一時的な値を設定します複数のmips引数を使用する> 4

li $t0,40 #temp value for our 5th arg. 

addi $sp, $sp, -4 #decrement stack pointer by 4 
sw $t0, 0($sp) #save the value of $t0 on the stack. 

jal printf 

は、スタック上のスペースを与え、それを保存します。私の機能が呼び出されます。

lw $t0, 0($sp) 
addi $sp, $sp, 4 
move $a0,$t0 

li $v0, 1 
syscall 

...それだけで出力します:これは働いていたかどうかを確認するための試験として、関数の内部で、私はその保存されたレジスタの対応にこれらの一時引数$ A0- $ A3を移動すると、私はこのコードを持っています0と40でないので、私は間違っている何かをしています。すべての支援を大幅に最も一般的な32ビットMIPS calling convention

答えて

1

感謝(とupvoted)されるだろう、スペースが$a0,$a1,$a2$a3のスタック上に確保された、いわゆる機能は16($sp)で5番目の引数を見つけることを期待すべきです。

これらの問題を理解する最も簡単な方法は、関数の空のバージョンをCで記述し、.oファイルを逆アセンブルして、引数がコンパイラによってどのように渡されるかを調べることです。

+0

レジスタにある引数のためにスタック上にスペースが予約されるのはなぜですか? Wikipediaのページによれば、引数5と4は1から4までではなく、スタックに渡されます。 – blackcompe

+1

これは呼び出し規約がどのように定義されているかを示し、呼び出されたルーチンが引数をスタック上の既知の場所に保存できるようにします。 wikiページが不完全です。 http://www.mips.com/media/files/MD00565-2B-MIPS32-QRC-01.01.pdfを参照してください。 – markgz

+0

私はあなたが意味するものを見て、あなたは正しいです。 – blackcompe

0

このコードは絶対に正しいので、問題は他の場所にあります。私の推測では、スタックポインタがコード内のそのポイントまで正確に管理されていないか、またはprintfでスタックをポップする前にエラーが発生していると思われます。なぜデバッガを使って何が起こっているのか見てみませんか?可能であれば、問題を示す無関係のコードをすべて外した実行可能プログラムを投稿してください。 Hereはあなたがやろうとしていることを行い、同じ指示を使用している実用的なMIPSプログラムです。

+0

http://cl.ly/0D1s2j2y400n2I1n2A1hは完全なプログラムです。 printf_branch_argsでは次の引数のアドレスを計算する必要がありますが、その方法はわかりません – jfisk

+0

@jfisk: 'printf_branch_args'という名前のラベルはありません。とにかく、それは私があなたを助けることができない複雑なコードです。私の目的は単に提示された質問に答えることでした。 – blackcompe

0

あなたが扱っている2つの問題は、上にリンクした完全なコードを見てからです。

1)スタックは、標準のMIPS o32呼び出し規約で引数(特に4つ以上)を使用するように正しく設定されていません。他の答えはあなたにこれを助けることを指摘する良い仕事をしています。

2)使用している 'printf'は、標準の呼び出し規約を使用していません。コメントが表示された場合:

## printf-- 
## A simple printf-like function. Understands just the basic forms 
## of the %s, %d, %c, and %% formats, and can only have 3 embedded 
## formats (so that all of the parameters are passed in registers). 
## If there are more than 3 embedded formats, all but the first 3 are 
## completely ignored (not even printed). 
## Register Usage: 
## $a0,$s0 - pointer to format string 
## $a1,$s1 - format argument 1 (optional) 
## $a2,$s2 - format argument 2 (optional) 
## $a3,$s3 - format argument 3 (optional) 
## $s4 - count of formats processed. 
## $s5 - char at $s4. 
## $s6 - pointer to printf buffer 

スタックには何も渡されません。 $ s0-6はスタック関連ではないことを覚えておいてください。この関数に$ a0->書式文字列と3つの引数($ a1、$ a2、$ a3)を指定できます。 これらのコメントは、$ s0- $ s6を破棄していることを示していますが、不完全なコードから、トレースされずにどれくらい復元されたかを言うことができます。要するに、あなたが見つけたこのprintfは便利かもしれませんが、あなたが学ぶはずのスタックコンベンションを使用せず、非常に限られています。あなたがそれを使用する許可を持っていると仮定して、変更するための許可を取得し、まったく何かにインターフェイスを書き直すことについてだけ見てください。一度に3つ以上の変数を印刷する必要がある場合は、関数を複数回呼び出す必要はありません(大文字小文字の場合は、ラッパーを記述してください)。

関連する問題