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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

5回答

3248閲覧

文字列をコピーする関数のMIPSコードによる記述

matti0518

総合スコア10

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2019/02/04 16:23

前提・実現したいこと

「以下のCコードで示した関数strcpyを$s0をiとして使ってMIPSのアセンブリコードで書き、また関数の実行前と実行中と実行後のスタックの様子を図示せよ。」
という課題が出されたのですがよくわからなかったので質問させていただきます。

主にわからない点は、
・以下のCコードにおけるdo while文の継続条件式の意味
・引数を使用していない関数なのにスタックポインタを使う理由($s0を退避させるだけでよいのか?退避させるべきレジスタは?)
です。

MIPSコードは書いてみましたが自信がないので、そちらの方も教えていただけると助かります。

該当のソースコード

C

1void strcpy(char dst[], char src[]) { 2 int i = 0; 3 4 do { 5 dst[i] = src[i]; 6 } while (src[i++]); 7}

MIPS

1#a0 = dstのベースアドレス、a1 = srcのベースアドレス 2 3strcpy: 4 addi $t4, 0x00 #$t4=0x00 5 addi $s0, $0 #$s0=i 6 addi $sp, $sp, -4 7 sw $s0, 0($sp) 8 9do: 10 add $t0, $t0, $a0 #address of dst[i] 11 add $t1, $t1, $a1 #address of src[i] 12 lb $t3, 0($t1) #$t3 = src[i] 13 sb $t3, 0($t0) #dst[i] = src[i] 14 beq $t3, $t4, done #if(dst[i] == \0) done 15 addi $s0, $s0, 1 #i=i+1 16 sll $t0, $s0, 2 #$t0 = i * 4 17 sll $t1, $s0, 2 #$t1 = i * 4 18 j do 19done: 20 lw $s0, 0($sp) 21 addi $sp, $sp, 4 22 23 jr $ra

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

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

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

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

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

guest

回答5

0

・引数を使用していない関数なのにスタックポインタを使う理由

スタック使うのは引数だけではありません。
この場合はローカル変数をスタックで実装してますね

投稿2019/02/04 22:00

y_waiwai

総合スコア87749

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

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

0

MIPSのアセンブラを見るのは20年振りなので少し自信がないのですが、気になった点を書いてみます
sll $t0, $s0, 2 #$t0 = i * 4
sll $t1, $s0, 2 #$t1 = i * 4

カウンタを4づつ進めるているようですが大丈夫でしょうか?
以下のコードは1byteづつコピーしていますよね?
lb $t3, 0($t1) #$t3 = src[i]
sb $t3, 0($t0) #dst[i] = src[i]

1バイトコピーして、カウンターを4つ進める・・・
4バイトおきに1バイトづつコピーされるコードにはなってませんか?

(あと$t0, $t1はテンポラリレジスタだと思いますが、初期化しなくても0になっている前提で使っていいものでしたっけ?)

投稿2019/02/05 03:19

takahirot

総合スコア16

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

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

0

do while文の継続条件式の意味

Cの真偽値は0がfalse,他がtrueです。よって「0でない間ループ」を意味します。
…というかこれはアセンブリで書けているので分かっているのでは。

引数を使用していない関数なのにスタックポインタを使う理由($s0を退避させるだけでよいのか?退避させるべきレジスタは?)

「引数を使用していない」という意味がよくわかりませんが、「引数をスタックで渡していない」という意味でしょうか。
今回ローカル変数をスタックで実装していませんので、s0を退避させるだけでよいです。
退避させるべきレジスタは、呼び出し規約で決められた、呼び出され側(callee)が保存するとされているレジスタのうち、実際に使用するものです。
今回わざわざ課題でs0を使用すると指定されていなければスタック不使用でも書ける内容です。(だからこそs0を指定されたんでしょうね)

アセンブリコードの内容としては、既出のものの他に、代入の仕方が全体的におかしいです。
addi $t4, 0x00
addi $s0, $0
add $t0, $t0, $a0
add $t1, $t1, $a1
このあたり、代入したいのだと思いますが、レジスタの既存の値に加算していますし、2引数なのは理解が間違っていそうです。
そもそもaddi $s0,$0ってアセンブル通るんですかね…?

代入はゼロレジスタへの加算やORで実現されます。
なお特に禁止でなければ、普通のアセンブラには疑似命令(レジスタ間コピーのmove・即値ロードのli)が用意されているのでこちらで書いたほうが分かりやすいでしょう。

投稿2019/02/06 01:36

編集2019/02/22 19:53
ikadzuchi

総合スコア3047

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

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

0

Mips ほとんど使った事が無い、、と Wiki-pediaMIPSアーキテクチャを見てみました。

とすると、

  • $s0 : 保存しなくてはいけないレジスタ
    addi $s0, $0 # $s0=isw $s0, 0($sp) の前にあるので、保存されていません。 順序が逆と思われます。 ただ、$T* は、一時変数のようなので、 $t2 とか、使ってはいけない?

  • 既に指摘がありますが、 $t0, $t1が初期化無しで使われています。 do: の前に、初期化すべきかと。

  • 既に指摘がありますが、 sll $t... は、4byteつづ、移動しています。

  • 更に、$t0, $t1 共に、同じ値(アドレス - ($s0 << 2) を設定しています。これでは、loopの2回目以降は、同じ場所へのコピーとなり、意味がありません。

  • 細かい話ですが、MIPSは、 $zeroは、常に 0みたいなので、 $t4 の代わりに使えませんか?

スタックポインタについては、これだけでは、退避するものはなさそうですね。
($s0 使わなければ、、、)

気が付いたところで。

投稿2019/02/05 13:32

pepperleaf

総合スコア6383

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

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

0

mips のアセンブラは分かりませんので C のほうだけになります.

C の文字列は 0 で終わります.
while は () の中が真の間ループします.
C では 0 は偽で, それ以外は真です.

この組み合わせです.

投稿2019/02/04 17:20

jimbe

総合スコア12632

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問