練習問題
演習1.3-1 以下の各プログラムを作成し,作成したソースコードを自分のGitHubリポジトリに提出(commit & push)しなさい。 リポジトリのルートディレクトリにサブディレクトリ chap3 を作り,その中に下記の演習課題のソースファイルを置くこと。新しいサブディレクトリ中のファイルも,これまでと同じく git add,git commit を実行すればよい。 ソースファイル名は各小問で指定する。異なる名前のファイルや異なるディレクトリに置かれているファイルは無視する(逆に言えば,提出物ではないファイルをリポジトリに置いても構わない)。期限は別途指示する。
提出後に自動検査システムが提出物を検査する。検査に合格しない提出物は未提出と同じ扱いとする。
全小問に関係する注意: 以下の演習問題はいずれも,「ラベル data
が指す番地を先頭とする ndata
個のダブルワードからなる列」を計算対象とする。元の data
・ndata
の定義を削除して別の data
・ndata
の定義に差し替えても正しい結果を出力するようにプログラムを作成すること。
なお,差し替え後の計算対象データ列は,アクセス可能領域の末尾である場合がある(つまり,計算対象データ列を超えて後ろにアクセスするプログラムは自動検査に合格しない)。
計算対象データ列のほかにもデータ領域を定義して使って構わない。
- ラベル
data
が指す番地を先頭とするndata
個のダブルワードからなる列について,その中の最大値を出力するアセンブリ言語プログラムを作成しなさい。ただし,各ダブルワードの値は0以上255以下,ndata
は1以上1万以下と仮定してよい。(提出ファイル名:max.s
) - ラベル
data
が指す番地を先頭とするndata
個のダブルワードからなる列について,中身を昇順に整列した後終了するアセンブリ言語プログラムを作成しなさい。例えば7個のダブルワードの列 3, 1, 4, 1, 5, 9, 2 が与えられた場合は,data
番地から始まる28バイトの領域の中がダブルワード列 1, 1, 2, 3, 4, 5, 9 となるよう書き換えた後,終了すればよい。プログラムの終了コードは 0 とすること。 (自動検査では,exitシステムコール実行時の主記憶の内容を検査する。) 整列対象の各ダブルワードは0以上231未満とする(符号の有無を考慮しなくてよい)。ndata
は1以上300以下とする。 (提出ファイル名:sort.s
)- (オプション項目) 30万個の乱数の列に対して適用しても2秒以内に整列を終了する場合は,加点する。
(ヒント)
- データ列の総和を計算するプログラムとアルゴリズムはほとんど同じ。主記憶の扱い方を確認するための問題。オーバーラン(データ列の範囲を超えて外にアクセスすること)をしないように注意。
- 整列アルゴリズムは自由に選んでよい。バブルソートがおそらく一番単純だが(といってもここまでの課題よりはずっと複雑),選択ソートや挿入ソートでも大差はない。まずはC言語やJavaで整列アルゴリズムを正確に書いてから,それを翻訳していくのが良い。安易に最初からアセンブリ言語で書こうとするとほぼ確実に破綻し,永遠に完成しなくなるであろう。
オプション項目を満たすためには平均 O(n log n)〜O(n√n) 時間程度のアルゴリズム(クイックソート,マージソート,ヒープソート,シェルソート,etc.)を実装する必要がある。なお,自信がある場合も,最初はバブルソート等で作成し,検査に合格してから高速アルゴリズムに変更する方が安全。
(小問2 動作確認のヒント)
小問2は,一つの値を出力するという問題ではないので,動作確認が少し難しい。 自動検査システムに検査を任せるのも一案だが,提出前に確認したければ,動作確認処理も含めてプログラムする,という方法もある。 つまり,整列処理が終わったあと,整列結果が正しいことを確認してから終了する(整列結果が正しいか正しくないかを終了コードで知らせる)ようにプログラムする。 整列対象データ列とそれを整列したデータ列の両方をプログラム中に記述して,整列処理後に両者が一致するか調べればよい。
なお,自動検査システムは整列対象データを差し替えて検査を行うので,提出時には動作確認処理は取り除く(ジャンプで飛び越えたりコメントアウトしたりして実行しないようにする)必要がある。
最終課題
- 上記の演習1.3-1 小問1〜2のプログラムを作成し,提出しなさい。自動検査に合格しない提出物は未提出と同じ扱いとする。
- 演習1.3-1 小問2のプログラム(
sort.s
)に関して実験レポートを作成しなさい。詳細はKUTLMSに掲載する。