Subsections

2 [例題8]アドレスの受け渡し

2.1 サブルーチンを実現するために必要なこと

プログラムの規模が大きくなると,その動作の内容が分かりにくくなる.また,似たよう な処理が増えてくる.そのため,プログラムを機能毎に分割することが行われている.機 能毎に分割した,専用のプログラムを利用するのである.このことにより というようなメリットが生じる.この機能毎に分割したプログラムの単位をサブルーチン と言う.いわゆるプログラムの部品みたいなものである.一般には,サブルーチンは簡単 な機能を持つ単純な構造にする.複雑な動作をするものが一つあるよりも,単純なものを組 み合わせて複雑な動作をさせる方が簡単である.

実際のプログラムでは,図1の様な構造となる.一番左のSTARTから ENDのラインがメインルーチンである.そして,処理Aから処理Dのラインが,それぞれサ ブルーチンとなっている.このようにサブルーチンが集まり,プログラムができあがる. 実際の動作は,呼び出されたサブルーチンが順次動作し,プログラムが実行される.

図 1: サブルーチンを使ったプログラムの構造
\includegraphics[keepaspectratio, scale=0.8]{figure/subroutine.eps}

サブルーチンはプログラムの部品であると先程述べた.それが部品となるためには,他の プログラムにも転用可能である必要がある.ボルトは機械要素の部品である.これは,自 動車にも使えるし,飛行機,冷蔵庫などあらゆるものに使える.自動車にしか使えないボ ルトとなると用途が限られ,部品としては役割が小さくなる.部品として有用になるため には,汎用性が重要となる.サブルーチンも同じで,これが有用となるためにはどのプロ グラムでも使えるようにしなくてはならない.

このような観点から,教科書 [1]の[例題7]のプログラムを見る.そのプ ログラムはリスト1の通りで,最大値を検索サブルーチンを使ったプ ログラムとなっている.9〜20行がサブルーチンである.このサブルーチンの部分を他の プログラムで使おうとすると,DATAMAXの部分を書き直す必要がある.プロ グラム毎に書き直す必要があるので汎用性があるとは言い難い.あまり良いサブルーチン とは言えない.

サブルーチンのプログラムを書き換えることなく,他のプログラムでも使えるようにしな くてはならない.そのためには,重要なデータ,ここではDATAKOSUUMAXを引数として受け渡しすればよい.実際のプログラム方法は,教科書のList5-8 で学習する.

[caption=サブルーチンを使ったプログラム例,label=prog:List_5_7] program/text_list_5_7e.cas

2.2 データの渡し方

教科書のp.102にちょっと分かりにくいプログラムが載せてある.C言語が分かる人はこ こで何が言いたいか分かるが,諸君は学習していないのであまりにも唐突に思えるだろう. 分からない人は,気にしないでも良い.

サブルーチンにデータを渡す方法は,2種類ある.アドレス渡し値渡しで ある.図2のようにメモリーにデータがあるとする.アドレス #0042のデータ#1234 をサブルーチンで処理する場合,それを渡す必要があ る.この場合,

アドレス渡し
処理するデータのアドレス#0042をサブルーチンに渡 す.この場合,サブルーチンはアドレスを知ることが出きるので,#0042 番地の 内容を書き換えることができる.
値渡し
処理するデータの値#1234をサブルーチンに渡す.この場合, サブルーチンはアドレスが分からないので,#0042 番地の内容を書き換えること ができない.
である.いずれにしても,サブルーチンは,処理すべきデータ#1234を知ることがで きるが,アドレス#0042の内容を書き換えることができるか否かが異なる.

どちらの方法を使うかは,処理の内容により異なる.諸君が経験を積めば,どちらを使う べきか分かるだろう.ここでは,そこまで踏み込まないことにする.

図 2: サブルーチンへ処理すべき内容を渡す方法
\includegraphics[keepaspectratio, scale=0.8]{figure/data_memory.eps}

2.3 教科書の例

教科書の[例題8]は,[例題6]や[例題7]同様,最大値データの最大値を求めるプログラム である.これらのプログラムで解く問題は, である.同じ問題を解いているが,それぞれプログラムの方法が異なっており,少しずつ プログラムが以下のように進化している.

すでに,[例題7]までの学習は完了している.ここでは,[例題7]から[例題8]への進化の 過程を学習する.ここでの進化は,最大値を捜す関数の独立性を高め,サブルーチンを書 き換えることなく,他のプログラムに移植可能にしたことである.それを可能にするため には,サブルーチン内では,DATAKOSUUMAXという文字を書かないこ とである.しかし,これらはサブルーチンでの処理上,極めて重要なデータとなっている ので,そのデータの内容はサブルーチンに伝える必要がある.このような場合,引数を使 うのが常套手段である.教科書のList 5-8では,次節に示すように,汎用レジスターを使っ てデータの受け渡しをしている.このようにすると,呼び出し側でレジスターに入れる変 数を変えるだけで,サブルーチンはどのようなルーチンからでも呼び出しができるように なる.

汎用的なサブルーチンは,どんなプログラムからでも呼び出しができるようにしなくては ならない.[例題10]のList5-10では,割り算のサブルーチンが使われており,これは頻繁 に使われるので,レジスターを使ってデータを渡している.どんな呼び出し元であれ,レ ジスターの値を変えるだけで,サブルーチンに処理を依頼できる.

2.4 プログラムの構造とフローチャート

このプログラムのフローチャートを図3に示す.このプログ ラムを理解するために,ここで使われているレジスターやラベルの内容を表 4に示しておく.

汎用レジスターのGR1GR2GR3を使って,サブルーチンで処理に必要な データDATAKOSUUMAXを送っている.こうすると,他のルーチンから もデータの先頭アドレスと個数,最大値を格納するアドレスを送れば,このサブルーチン が処理できる.ほかのルーチンでのラベル名が異なっても,このサブルーチンが使えるの である.

サブルーチンでは,GR1GR5を使って処理をしている.サブルーチンが終了す るときには,メインルーチンで使っているこれらのレジスターを元に戻さなくてはならな い.サブルーチンがメインルーチンの動作に関与する可能性が生じるからである.そのた めに,次のような動作が必要である.

これらのことを,PUSHPOP命令を使って,処理している.
表 1: 汎用レジスターとメモリの内容
  メインルーチン サブルーチン
DATA データの先頭アドレス 未使用
KOSUU データ数が格納されたアドレス 未使用 
MAX 最大値を格納するアドレス 未使用
GR1 データ数 データ数-1
GR2 データの先頭アドレス 比較するデータのアドレス
GR3 最大値を格納するアドレス 最大値を格納するアドレス
GR4 未使用 カウンター(比較済みデータ数-1)
GR5 未使用 比較するデータ

図 3: 教科書のList 5-9のプログラムの構造とフローチャート
\includegraphics[keepaspectratio, scale=0.8]{flow_chart/REI5-8.eps}

ホームページ: Yamamoto's laboratory
著者: 山本昌志
Yamamoto Masashi
2006-02-16


no counter