基本情報技術者 2012年 春期 午後 問12
次のアセンブラプログラムの説明及びプログラムを読んで、設問1〜3に答えよ。
〔プログラム1の説明〕
主プログラムから渡された二つの数字列(数字列1と数字列2)をそれぞれ正の10進数とみなして加算し、結果を数字列で返す副プログラムADDCである。二つの数字列の加算の例を図1に示す。
(1) 汎用レジスタGR1〜GR5には、それぞれ次の内容が設定されて、主プログラムから渡される。
GR1:数字列1の先頭アドレス
GR2:数字列2の先頭アドレス
GR3:結果領域の先頭アドレス
GR4:数字列1の長さ(文字数)
GR5:数字列2の長さ(文字数)
(2) 数字は1語に1文字格納する。
(3) 結果の数字列は結果領域に格納し、長さ(文字数)はGR0に設定して、主プログラムに返す。
(4) 数字列1と数字列2の長さ(文字数)は、それぞれ1以上とする。
(5) 数字列1と数字列2の左端の文字は“0”でないものとする。
(6) 副プログラムから戻るとき、汎用レジスタGR1〜GR7の内容は元に戻す。

設問1:
問題文を見る プログラム1中のに入れる正しい答えを、解答群の中から選べ。
解答群
ア:SUBA GR4,=1
イ:SUBA GR4,=9
ウ:SUBA GR4,=10
エ:SUBA GR5,=1
オ:SUBA GR5,=9
カ:SUBA GR5,=10
キ:SUBA GR6,=1
ク:SUBA GR6,=9
ケ:SUBA GR6,=10
模範解答
a:ケ、b:ア、c:エ
解説
解答の導き方
この設問では、プログラムが数字を右端から1桁ずつ加算する流れを確認し、a〜cに入る処理を考えます。
1. GR4側を長い数字列にそろえます
3〜10行目では、数字列の長さを比べ、必要ならポインタと長さを入れ替えています。これにより、以降はGR4が長い数字列の残り文字数、GR5が短い数字列の残り文字数になります。
11、12行目では、GR1とGR2にそれぞれの長さを足しています。ポインタを数字列の末尾の次の位置に進め、15行目や18行目で1ずつ戻って末尾の数字を読み取るためです。
2. 桁上がりがある場合は、加算結果から10を引きます
GR0は桁上がりを表します。13行目で0に初期化され、20行目で現在の桁の計算に加えられます。
17行目のANDは、数字の文字から数字部分だけを取り出す処理です。一方、19行目ではGR1側の数字の文字を加えています。数字の文字は文字コードで扱われるため、21行目では結果を文字「9」と比べています。
結果が「9」より大きければ、22行目からCARRYに進みます。このとき、加算した値は1桁に収まらないので、次の桁への桁上がりをGR0に設定します。加算結果の1桁を正しく戻すには、10を引けばよいため、aには SUBA GR6,=10 が入ります。
例えば、ある桁の合計が13なら、次の桁へ1を繰り越し、現在の桁には3を残します。10を引くことで、13から3を取り出せます。
3. 加算した桁数に応じて、残りの数字を処理します
27行目では、計算した1桁をスタックに保存します。スタックは、データを一時的に積み重ねて保存する場所です。右端から計算した数字を最後に逆順で取り出すために使います。
その直後の28行目では、長い数字列から1桁を処理したことを記録する必要があります。長い数字列の残り文字数はGR4なので、1減らす SUBA GR4,=1 がbに入ります。
29行目のJZEは、GR4が0になったかを調べます。長い数字列を最後まで処理していたら、残りの桁を読む必要はありません。
まだ長い数字列の桁が残っている場合は、30行目で短い数字列の残り文字数GR5を1減らします。したがってcには SUBA GR5,=1 が入ります。
31行目のJPLは、減らした後のGR5が正の値かを調べます。まだ短い数字列に桁が残っていれば、LOOP1に戻って次の桁同士を加算します。短い数字列が終わっていれば、32、33行目でGR6を0にしてLOOP2に進みます。これにより、長い数字列の残りを、桁上がりだけを加えながら処理できます。
4. スタックから取り出して、結果を左から格納します
加算は右端から進みますが、スタックから取り出すときは最後に保存した数字から出てきます。そのため、39行目以降で取り出すと、結果を左端から順に結果領域へ格納できます。
最後に桁上がりが残っていれば、36行目で左端に「1」を追加します。GR0は、結果の桁数を数える役割も持ち、結果を格納するたびに42行目で増やされます。
誤りやすいポイント
-
aで9を引かないこと
10進数では、桁上がりを起こす境目は10です。合計から10を引くと、現在の桁に残す数字が得られます。 -
bでGR5を減らさないこと
27行目で処理したのは長い数字列の1桁です。その残りの長さを記録しているのはGR4です。 -
cでは短い数字列の残りを調べること
短い数字列が終わった後も、長い数字列には桁が残る場合があります。その場合は、短い数字列の数字を0とみなして計算を続けます。 -
右から計算した数字を、そのまま結果領域に書かないこと
スタックに一時保存してから取り出すことで、結果を左から順に格納できます。
FAQ
Q: GR4とGR5を入れ替えるのはなぜですか?
A: 長い数字列の残りをGR4で管理し、短い数字列が終わった後も計算を続けられるようにするためです。長さが同じ場合に入れ替わっても、処理に問題はありません。
A: 長い数字列の残りをGR4で管理し、短い数字列が終わった後も計算を続けられるようにするためです。長さが同じ場合に入れ替わっても、処理に問題はありません。
Q: 短い数字列が終わった後、なぜGR6を0にするのですか?
A: 長い数字列の残りの桁には、短い数字列から足す数字がありません。その桁を0として扱い、桁上がりだけを加えるためです。
A: 長い数字列の残りの桁には、短い数字列から足す数字がありません。その桁を0として扱い、桁上がりだけを加えるためです。
Q: GR0は桁上がりと結果の長さの両方に使われるのですか?
A: はい。加算中は桁上がりを表し、結果を書き始める段階では、先頭に桁上がりを追加するかどうかを示します。その後、格納した結果の桁数を数えます。
A: はい。加算中は桁上がりを表し、結果を書き始める段階では、先頭に桁上がりを追加するかどうかを示します。その後、格納した結果の桁数を数えます。
関連キーワード: アセンブリ言語、汎用レジスタ、スタック、桁上がり、10進数加算、条件分岐
設問2:
問題文を見る 次の記述中のに入れる正しい答えを、解答群の中から選べ。
図1の数字列1と数字列2を引数として副プログラムADDCを実行した場合、行番号25のLD命令はd回実行される。
解答群
ア:0
イ:1
ウ:2
エ:3
オ:4
模範解答
d:エ
解説
解答の導き方
行番号25の「LD GR0,=1」は、桁の計算で桁上がりが起きたときに実行されます。行番号21で計算結果を「'9'」と比べ、結果がそれより大きい場合に、行番号22から「CARRY」へ進むためです。
図1の数字列は、右端の桁をそろえて計算します。桁ごとの計算は次のとおりです。
数字列2には左端の桁がないため、左端の計算では数字列2の値をとして扱います。前の桁からの桁上がりも加えるので、です。
この結果、行番号25は3回実行されます。最後に残った桁上がりは、行番号34で確認し、行番号36で「'1'」として結果に追加します。この処理では行番号25を実行しません。
したがって、示された図1の数字とプログラムに基づくと、行番号25の実行回数は3回です。提示された模範解答の「エ:4」とは一致しません。
誤りやすいポイント
- 結果が「10135」と5桁になるため、行番号25も5回実行されると考えないようにします。行番号25は、桁上がりが発生した計算でだけ実行されます。
- 一番右の桁ではとなり、桁上がりはありません。
- 最後に結果へ追加される「'1'」は、行番号36で設定されます。行番号25で設定される桁上がりフラグとは別の処理です。
FAQ
Q: 数字列2に桁がない左端は、どう計算しますか?
A: その桁の数字列2の値をとして扱います。この例では、左端をと計算します。
A: その桁の数字列2の値をとして扱います。この例では、左端をと計算します。
Q: 行番号25は、どんなときに実行されますか?
A: その桁の計算結果が「'9'」より大きくなり、行番号22から「CARRY」へ進んだときに実行されます。
A: その桁の計算結果が「'9'」より大きくなり、行番号22から「CARRY」へ進んだときに実行されます。
Q: 結果の左端に追加する「'1'」も、行番号25の実行回数に含めますか?
A: 含めません。行番号34で桁上がりを確認したあと、行番号36で「'1'」を設定します。
A: 含めません。行番号34で桁上がりを確認したあと、行番号36で「'1'」を設定します。
関連キーワード: 10進数加算、桁上がり、桁上がりフラグ、条件分岐
設問3:
問題文を見る 副プログラムADDCを使用して、n個(n ≧ 1)の数字列を入力し、総和を求めて数字列で出力するプログラムSUMCを作成した。n = 5の場合の例を図2に示す。
プログラム2中のに入れる正しい答えを、解答群の中から選べ。
なお、入力される数字列、総和は256桁以内に収まるものとする。


解答群
ア:LAD GR3,BUF1
イ:LAD GR3,BUF2
ウ:LAD GR3,BUF3
エ:LD GR3,GR0
オ:LD GR4,GR0
カ:LD GR5,GR0
模範解答
e:オ、f:ウ
解説
解答の導き方
この問題では、数字列を順に加算するプログラムについて、加算後の「長さ」と「総和を格納した場所」をどのように扱うかを考えます。
汎用レジスタ(計算値やデータの場所などを一時的に入れておく場所)と、ポインタ(データが置かれた場所を指す情報)の役割を確認しましょう。
-
加算後の長さを次の計算に引き継ぎます最初の数字列はBUF1に入り、その長さはGR4に設定されています。次の数字列はBUF2に入り、その長さはGR5に設定されます。ADDCは、この二つを加算して、GR3が指す場所に結果を格納します。プログラム1の説明には、結果の長さをGR0に設定して返すとあります。一方、ADDCから戻るときにはGR1〜GR7の内容が元に戻ります。そのため、GR4には加算前の長さが残り、結果の長さはGR0にあります。次の加算では、今の総和を数字列1として使います。そこで、次の数字列1の長さをGR4に入れる必要があります。空欄eには、GR0の値をGR4に移す LD GR4,GR0 が入ります。解答群ではオです。
-
総和を格納する場所を交互に切り替えます加算後のプログラムでは、次の3行でGR1とGR3を入れ替えています。
- GR1は、次に数字列1として使う場所を指します。
- GR3は、次の加算結果を書き込む場所を指します。
これにより、今ある総和を読みながら、その総和を同じ場所に上書きするのではなく、BUF1とBUF3を交互に使えます。入力が1つ増えるたびに、総和が入る場所も入れ替わります。 -
入力終了後、総和がどちらの領域にあるかを判定します入力が終わると、GR1は現在の総和が入っている場所を指しています。しかし、GR3は入れ替えの結果、BUF1を指している場合もBUF3を指している場合もあります。そこで、空欄fでGR3をBUF3の先頭アドレスに設定します。LAD GR3,BUF3 とすれば、続くCPA GR1,GR3で、GR1がBUF3を指しているかを判定できます。
- GR1とGR3が等しければ、総和はBUF3にあります。JZE FIN2の後でBUF3を出力します。
- 等しくなければ、総和はBUF1にあります。BUF1を出力します。
解答群ではウです。入力が1つだけの場合も、GR1はBUF1を指しているため、この判定で正しくBUF1を出力できます。
誤りやすいポイント
- GR0とGR4を取り違えないようにしましょう。ADDCが結果の長さを返すのはGR0です。次の加算で使う長さの領域がGR4なので、GR0からGR4へ移します。
- ADDCがGR1〜GR7を元に戻すため、GR4も結果の長さに自動で更新されるわけではありません。ここが空欄eを考えるポイントです。
- 空欄fで設定するのは「今回の総和が入っている場所」ではなく、BUF3のアドレスです。実際に総和がBUF3にあるかどうかは、その後の比較で調べます。
FAQ
Q: なぜ加算結果をBUF1とBUF3に交互に格納するのですか?
A: 加算に使う総和を残したまま、別の領域に次の結果を書き込むためです。交互に使えば、読み取っている数字列を結果で上書きするのを避けられます。
A: 加算に使う総和を残したまま、別の領域に次の結果を書き込むためです。交互に使えば、読み取っている数字列を結果で上書きするのを避けられます。
Q: 入力が1つだけでも、空欄fの処理は必要ですか?
A: 必要です。入力が1つだけなら、総和は最初からBUF1にあります。GR3をBUF3に設定して比較することで、BUF1を出力する分岐に進めます。
A: 必要です。入力が1つだけなら、総和は最初からBUF1にあります。GR3をBUF3に設定して比較することで、BUF1を出力する分岐に進めます。
Q: なぜGR1とGR3の比較だけで、出力先を決められるのですか?
A: 総和を格納する領域はBUF1とBUF3の二つだけだからです。GR3をBUF3に設定したうえでGR1と比べれば、等しい場合はBUF3、等しくない場合はBUF1と判断できます。
A: 総和を格納する領域はBUF1とBUF3の二つだけだからです。GR3をBUF3に設定したうえでGR1と比べれば、等しい場合はBUF3、等しくない場合はBUF1と判断できます。
関連キーワード: 副プログラム、汎用レジスタ、ポインタ、アドレス、ループ処理




