2016-10-14 18 views
0

私は現在、ci20マシン上の小さなプログラムで作業しており、ユーザに整数値を入力させ、画面に値を表示します。アセンブリのci20 segフォルトでユーザ入力を促す

私の現在のコード

.data 

prompt: 
.asciiz "Please enter an integer: " 
message: 
.asciiz "\nValue entered: " 

.text 
.global main 

main: 
    addiu $sp, $sp, -4 # push stack 
    sw $ra, ($sp)  # save return address 

    addi $v0, $0, 4 
    la $a0, prompt 
    syscall   # printing prompt 

    addi $v0, $0, 5 
    syscall   # get user input 

    move $t0, $v0  # save input in $t0 
    move $a0, $v0 
    addi $v0, $0, 1 # Not sure if this is right to print message 
    la $a0, message # Not sure if this is right to print message 
    syscall 

    lw $ra, ($sp)  # restoring $sp 
    addiu $sp, $sp, +4 # release the stack space used for $sp 

私はワンセグ障害を取得し、プログラムを実行しようとする理由がわかりません。どんな助けや提案も大歓迎です。

答えて

3

編集:何らかの理由で私はこのコードを完全に無視し、ci20マシンでテストしました。

これはLinuxですか?次に、MARSのシステムコールを使用することはできません。代わりに、Linuxのシステムコールを見つける必要があります。引き続き、最初のsyscall命令でセグメンテーションが行われます。これは、Linuxでは引数が無効であるためです。あなたがv0 = 1, a0 = messageとしてシステムコールの引数を設定し、「メッセージ」を表示するように... v0 = 4, a0 = promptとして設定された引数でsyscallを使用し、「プロンプト」を表示するには


これがMARSの場合、v0 = 1は「印刷整数」なので、a0は「メッセージ」文字列のアドレスではなく、整数である必要があります。あなたはおそらく、v0 = 4とv0 = 1(引数a0は "メッセージ"であり、特定の呼び出しのためのユーザー整数)で2回syscallを呼び出すことをお勧めします。

とにかく、これはsegfaultではありません。おそらく最後にコードがaddiu $sp, $sp, +4で終了し、raに戻りません。または、コードの開始時にraを保存してから、exitよりも戻りたいと思うように見えます。それはあなた次第です)。そのため、実行はいくつかのランダムな命令(初期化されていないメモリ内容)で継続されます。

とにかく2、あなたはそれ以上のデバッガとのステップで、このコードは命令による指示、その後、あなたはそれがセグメンテーション違反場所を正確に言うことが可能になりますどのように負荷把握する必要があり、そしてセグメンテーションフォルト命令の前のレジスタの内容は何でした。あなたのコードがsegfaultsで、あなたがどこにいなくても、それはあなたの側で努力の欠如を示しています。

(免責事項:私はMIPSのアセンブリをしたことがないので、私はほとんどそれがどのように動作するかを推測していると、何かを見落としている場合があります)


syscallについて編集、多分このヒントは、あまりにも役立ちますか!

syscallは、CPU上のすべての面白いことをやっている魔法の指示ではありません。ちょうどいくつかのハンドラルーチンにジャンプします。

このハンドラコードは、OSによって設定されます。 SO上のMIPSアセンブリリストのほとんどは、Linuxとはまったく異なるハンドラを持つMARSまたはSPIMを対象としています。

MIPSのためのlinux ABIと、そこでのシステムコールの使用方法について学ぶ必要があります。そして、Linuxのシステムコールテーブルを見つけると、おそらく大量のx86ドキュメントがあるので、それをv0/a0/... ABIに変換する必要があります。

MARSの例に従うことはできますが、OSの操作は調整する必要があり、すべてのオプションを見つけることはできません。例えば、数字を出力することはlinuxでは利用できません。自分で数値の値をASCII文字列に変換する必要があります(1桁の数字に '0'を加えれば十分です.9を超える数字の場合は、10の累乗ごとに数字を計算し、ASCII文字に変換してバッファ)、そして文字列をsys_write/etcで出力します。 (またはlibcとリンクして、Cライブラリのsprintfのような関数を呼び出す)。

+0

Linuxの読み込み/書き込みシステムコールは、ファイル記述子(例えば、標準入力の場合は0、標準出力の場合は1)、バッファアドレスとバイト数を取る必要があります。 –

+0

応答@ Ped7gありがとうございました。私はgdbを実行しているLinuxベースのマシンであるci20マシンでプログラムを実行しています。私がgdbデバッガを使って実行すると、seg faultが発生しないため、なぜseg faultであるのかという混乱が生じます。 – TurtleMan

+0

@TurtleManの場合、引数はsegfaultには十分な毒性はありませんが、linuxではなくsyscallにMARS引数を使用しています。ウェブ上で簡単に見れば、これはコンソールに何かを出力すると思います: '' v0' = '4'(sys_write)、' a0' = '1'(ファイル記述子stdout)、' a1' = 'prompt' .ascii文字列)、 'a2' =' 25'(.ascii文字列の長さ) 'syscall'です。これを最初の短いコードで試してみてください。ああ、 'v0' =' 1'はsys_exitです(終了コードに 'a0'という値があります)。おそらく、最初のものとしてa0 = 123と 'echo $?'をテストして、終了コードが123であるかどうかを調べるでしょう。 – Ped7g

関連する問題