質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
アセンブリ言語

アセンブリ言語とは、機械語を人間にわかりやすい形で記述した低水準言語です。

Q&A

解決済

1回答

861閲覧

C言語のmystrcatをアセンブリ言語に翻訳することができない。

caffeine-xox

総合スコア1

アセンブリ言語

アセンブリ言語とは、機械語を人間にわかりやすい形で記述した低水準言語です。

0グッド

0クリップ

投稿2022/06/16 01:21

C言語における、次のようなmystrcat関数

void mystrcat(char *s, char *t) { int i = strlen(s); strcpy(s+i, t); }

を、MIPSのアセンブリ言語に翻訳する、という課題です。

MIPSにおけるmain関数、及びmystrcat関数以外の関数は以下のようになっています。

.data nl: .asciiz "\n" s: .space 20 t: .asciiz " World" .text .globl main main: add $sp, $sp, -36 sw $ra, 0($sp) sw $s0, 4($sp) sw $s1, 8($sp) sw $s2, 12($sp) sw $s3, 16($sp) sw $s4, 20($sp) sw $s5, 24($sp) sw $s6, 28($sp) sw $s7, 32($sp) li $s0, 19 li $s1, 17 li $s2, 13 li $s3, 11 li $s4, 7 li $s5, 5 li $s6, 3 li $s7, 2 la $a0, s li $t0, 'H' sb $t0, 0($a0) li $t0, 'e' sb $t0, 1($a0) li $t0, 'l' sb $t0, 2($a0) li $t0, 'l' sb $t0, 3($a0) li $t0, 'o' sb $t0, 4($a0) sb $zero, 5($a0) la $a1, t jal mystrcat la $a0, s jal print_str # まず「Hello World」<改行> が表示され, la $a0, s sb $zero, 0($a0) la $a1, t jal mystrcat la $a0, s jal print_str # 次に「 World」<改行> が表示されればOK move $t0, $s0 mul $t0, $t0, $s1 mul $t0, $t0, $s2 mul $t0, $t0, $s3 mul $t0, $t0, $s4 mul $t0, $t0, $s5 mul $t0, $t0, $s6 mul $t0, $t0, $s7 sub $a0, $t0, 9699690 jal print_int # 最後に0<改行>が表示されれば恐らく$snの使用法ミスはなし($snの使用法チェックコードの実行結果) lw $ra, 0($sp) lw $s0, 4($sp) lw $s1, 8($sp) lw $s2, 12($sp) lw $s3, 16($sp) lw $s4, 20($sp) lw $s5, 24($sp) lw $s6, 28($sp) lw $s7, 32($sp) add $sp, $sp, 36 jr $ra print_int: li $v0, 1 syscall la $a0, nl li $v0, 4 syscall jr $ra print_str: li $v0, 4 syscall la $a0, nl li $v0, 4 syscall jr $ra strlen: move $v0, $zero strlenloop: lb $t0, 0($a0) beq $t0, $zero, strlenexit add $v0, $v0, 1 add $a0, $a0, 1 j strlenloop strlenexit: jr $ra strcpy: strcpyloop: lb $t0, 0($a1) sb $t0, 0($a0) addi $a1, $a1, 1 addi $a0, $a0, 1 bne $t0, 0, strcpyloop jr $ra

これにmystrcat関数を導入し、実行結果として

Hello World World 0

と表示されれば成功となります。

私は、以下のmystrcat関数を作成しました。

mystrcat: sw $a0, 0($sp) move $t6, $ra jal strlen lw $a0, 0($sp) add $a0, $a0, $v0 jal strcpy move $ra, $t6 jr $ra

それを実行した結果、上記の実行結果が得られることは分かったのですが、最後の「jr $ra」でエラーが発生し、以下のようなエラーが発生してしまいました。

Exception occurred at PC=0x100c7e08 Bad address in text read: 0x100c7e08 Exception 6 [Bad instruction address] occurred and ignored Exception occurred at PC=0x100c7e0c Bad address in text read: 0x100c7e0c Exception 6 [Bad instruction address] occurred and ignored Exception occurred at PC=0x100c7e10 Bad address in text read: 0x100c7e10 Exception 6 [Bad instruction address] occurred and ignored Exception occurred at PC=0x100c7e14 Bad address in text read: 0x100c7e14 Exception 6 [Bad instruction address] occurred and ignored Exception occurred at PC=0x100c7e18 Bad address in text read: 0x100c7e18 Exception 6 [Bad instruction address] occurred and ignored Exception occurred at PC=0x100c7e1c Bad address in text read: 0x100c7e1c Exception 6 [Bad instruction address] occurred and ignored Exception occurred at PC=0x100c7e20 Bad address in text read: 0x100c7e20 //以下アドレスが変わりながら同じエラーメッセージを繰り返す//

レジスタの退避先がおかしいのでしょうか?色々試してはみたのですが、改善できませんでした。
アセンブリ言語は初学なため、レジスタの退避の仕組みなどの理解に関してはかなり浅い理解となってしまっており、細かな点に関しては全くわかりません。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

caffeine-xox

2022/06/16 01:30

関連記事の貼り付けをしていただき、ありがとうございます。 私と同様な質問があったことは把握しておりますし、この質問でのやり取りを参考にして上の構文を作成しました。ですが、上記のエラーが発生してしまったため、どうしようもなくなってしまった、という状態になってしまっています。そのためこの質問を作成しました。
guest

回答1

0

ベストアンサー

  • 0($sp) は呼び出し元で使用中の領域です。-4($sp) など、関数呼び出し時の $sp よりも若いアドレスの領域を使ってください。そして、他の関数を呼ぶ前に $sp がスタック使用中の一番若いアドレスを指すように調整する必要があります。なので、main でやっているように冒頭で$spの値を必要なだけ減らして、0($sp) 4($sp) などを使うのが常套手段です。

  • $t6strlenstrcpy の呼び出しで破壊される可能性があります(*1)。$ra はスタックか $s0$s7 などに保存しておきましょう(*2)。

*1: この質問の strlenstrcpy の実装は $t6 を使っていませんが、MIPS の決まりとして破壊されるかもしれないレジスタとして扱います。

*2: しかし $s0$s7 に保存するなら、その元の値をやはりスタックなどに保存しておく必要があるので、けっきょく $ra はスタックに保存するのが手っ取り早いです。

投稿2022/06/16 01:40

編集2022/06/16 02:02
int32_t

総合スコア20872

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

caffeine-xox

2022/06/16 02:33

ありがとうございます、解決致しました。 $raはスタックへ退避、しっかり理解することができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問