HOME»基本情報技術者平成30年春期問題»午後問12
基本情報技術者過去問題 平成30年春期 午後問12
⇄問題文と設問を画面2分割で開く⇱問題PDF⇱アセンブラ言語の仕様問12 ソフトウェア開発(アセンブラ)
次のアセンブラプログラムの説明及び,プログラムを読んで,設問1~3に答えよ。
〔プログラム1の説明〕
0~65534 の整数を表す数字から成る文字列(以下,数字列という)を数値に変換する副プログラム DTOB である。
〔プログラム1の説明〕
0~65534 の整数を表す数字から成る文字列(以下,数字列という)を数値に変換する副プログラム DTOB である。
- 文字列は,DC 命令の文字定数と同じ形式で主記憶に格納される。数字列 567 を格納した例を,図1に示す。
- 主プログラムは,数字列が格納されている領域の先頭アドレスを GR1 に,数字列の長さを GR2 に設定して,DTOB を呼ぶ。DTOB は,数値に変換して得た値を GR0 に格納して呼出し元に戻る。
- 副プログラム DTOB から戻るとき,汎用レジスタ GR1~GR7 の内容は元に戻す。
設問1
プログラム1中の に入れる正しい答えを,解答群の中から選べ。
a に関する解答群
- ADDL GR5,GR4
- SLL GR4,1
- SLL GR4,2
- SLL GR5,1
- SLL GR5,2
解答選択欄
- a:
解答
- a=オ
解説
〔aについて〕
上部のコメント「GR0を10倍にしてGR4を加算」を行うための一連の処理の一部です。これは、数字を取り出した後、現在までの数字を10倍して桁上げする処理に該当します。例えば、GR0 に56が格納されている状態で、次に取り出した数字が7ならば「56×10+7=567」を GR0 に格納するなどです。
コメントが付されている行以降の処理をトレースしてみると、
GR5 には元の値の2倍にした値が入っているので、GR5 の値を左に2ビットシフトし、22=4倍することで「2×4=8倍」にする処理が適切です。
∴a=オ:SLL GR5,2
上部のコメント「GR0を10倍にしてGR4を加算」を行うための一連の処理の一部です。これは、数字を取り出した後、現在までの数字を10倍して桁上げする処理に該当します。例えば、GR0 に56が格納されている状態で、次に取り出した数字が7ならば「56×10+7=567」を GR0 に格納するなどです。
コメントが付されている行以降の処理をトレースしてみると、
- SLL GR0,1
- GR0 を1ビット左シフトさせています。これにより GR0 の値は2倍になります。
- LD GR5,GR0
- GR5 に GR0 の値をロードしています。これにより GR5 には GR0 の値が入ります。
- a
- ???
- ADDL GR0,GR5
- GR0 に GR5 の値を加算しています。
- ADDL GR0,GR4
- GR0 に GR4(取り出した数字)の値を加算しています。
GR5 には元の値の2倍にした値が入っているので、GR5 の値を左に2ビットシフトし、22=4倍することで「2×4=8倍」にする処理が適切です。
∴a=オ:SLL GR5,2
- GR4 は GR0 を10倍した後に加算することになっているので誤りです。
- そのまま加算すべき GR4 の値を左にシフトするので誤りです。
- 「イ」と同じ理由で誤りです。
- 左に1ビットシフトしただけだと元の値の4倍にしかなりません。
- 正しい。
設問2
文字列の先頭から数字列を探索し,順に,対応する数値を管理テーブルに格納する副プログラム GETWD を,DTOB を使用して作成した。プログラム2中の に入れる正しい答えを,解答群の中から選べ。
〔プログラム2の説明〕
〔プログラム2の説明〕
- 文字列は,一つ以上の空白文字で区切られた任意の個数の数字列を含み,最後はピリオドで終わる。最後の数字列とピリオドの間,又は文字列の先頭に一つ以上の空白文字があってもよい。文字列の例を,図2に示す。
- 管理テーブルには,文字列中に数字列が現れるごとに,順に1語から成る要素を追加し,数字列を数値に変換して得た値を格納する。数字列の探索が終了したとき,管理テーブルの最後に1語から成る要素を追加し,数値の終わりを示す印として-1を格納する。図2の文字列を GETWD で処理して得た管理テーブルを,図3に示す。
- 主プログラムは,文字列が格納されている領域の先頭アドレスを GR1 に,管理
テーブルの先頭アドレスを GR2 に設定して,GETWD を呼ぶ。 - 副プログラム GETWD から戻るとき,汎用レジスタ GR1~GR7 の内容は元に戻す。
b に関する解答群
- JNZ FIN
- JNZ LP
- JNZ NUM
- JZE FIN
- JZE LP
- JZE NUM
c に関する解答群
- JNZ FIN
- JNZ FIN2
- JNZ NUM
- JZE FIN
- JZE FIN2
- JZE NUM
d に関する解答群
- LAD GR6,1,GR1
- LAD GR6,1,GR6
- LAD GR7,1,GR2
- LAD GR7,1,GR7
- LD GR6,GR1
- LD GR7,GR2
解答選択欄
- b:
- c:
- d:
解答
- b=ウ
- c=イ
- d=エ
解説
〔bについて〕
[b]は分岐命令で、ここで分岐しない場合には次行で SETWD が呼ばれています。SETWD は、内部で DTOB が呼ばれていることからわかるように、GR1 に数字列の先頭アドレスを、GR2 に数字列の長さを格納して数値変換し、管理テーブルに追加する処理です。
ここで、文字列を1文字ずつ読み込んでいった際に数値変換を行うべき時点を考えてみると、以下のように数字列が続いた後に空白文字を読み込んだ場合と、数字列が続いた後に末尾のピリオドを読み込んだ場合の2通りあることがわかります。プログラムでは、空白またはピリオドを読み込むと SETWD を呼び出し、数字列の処理中であれば DTOB により変換した数値を管理テーブルに追加しています(ピリオドの場合はラベルFIN経由)。逆に数字を読み込んだ場合は、SETWD を呼び出す必要がないのでラベルNUMに分岐させることになります。CPL命令により読み込んだ文字と空白文字を比較し、一致しなければラベルNUMに分岐させたいので、[b]には「JNZ NUM」が入ります。
∴b=ウ:JNZ NUM
〔cについて〕
前述の通り、空白文字とピリオドを読み込んだ場合には SETWD が呼び出されますが、全ての場合に変換処理を行うのではなく、数字列の処理中の場合にだけ行う必要があります。逆に数字列の処理中でない場合は、何も行わず SETWD の呼出し元に戻らなければなりません。コメントにもあるように GR3 は、数字列の処理状態を示すフラグとなっており、0のとき数字列の処理中、-1のとき数字列の処理中ではないことを示します。[c]の直前でGR3の値をもとにフラグレジスタを設定しているので、GR3が0のときには DTOB を呼出し、そうではないときには何の処理も行わずRET命令で呼出し元に戻る処理が適切です。したがって[c]には、GR3 が0以外のときにラベルFIN2に分岐する「JNZ FIN2」が入ります。
∴c=イ:JNZ FIN2
〔dについて〕
[d]の3行前の DTOB 実行後、GR0 には数字列を数値に変換した値が格納されています。次行のST命令で、GR7 が保持するアドレスに GR0 の値を格納しています。GR7 はプログラムの4行目「LD GR7,GR2」で管理テーブルの先頭アドレスが格納されているので、この処理は管理テーブルに数値を追加する操作であることがわかります。管理テーブルは1つのアドレスに1つの数値を格納するので、数値を格納したら格納先のアドレスを1つ後ろに進めておかなければなりません。そうしないと同じアドレスを何度も上書きしてしまうことになります。
よって、GR7 のアドレスを1つ後ろに進める「LAD GR7,1,GR7」が適切です。
なお GR7 を更新している選択肢のうち、「ウ」は2つ目の数値以降、常に先頭アドレスの1つ後ろを更新することになるので誤り、「エ」は常に先頭アドレスを更新することになるので誤りです。
∴d=エ:LAD GR7,1,GR7
[b]は分岐命令で、ここで分岐しない場合には次行で SETWD が呼ばれています。SETWD は、内部で DTOB が呼ばれていることからわかるように、GR1 に数字列の先頭アドレスを、GR2 に数字列の長さを格納して数値変換し、管理テーブルに追加する処理です。
ここで、文字列を1文字ずつ読み込んでいった際に数値変換を行うべき時点を考えてみると、以下のように数字列が続いた後に空白文字を読み込んだ場合と、数字列が続いた後に末尾のピリオドを読み込んだ場合の2通りあることがわかります。プログラムでは、空白またはピリオドを読み込むと SETWD を呼び出し、数字列の処理中であれば DTOB により変換した数値を管理テーブルに追加しています(ピリオドの場合はラベルFIN経由)。逆に数字を読み込んだ場合は、SETWD を呼び出す必要がないのでラベルNUMに分岐させることになります。CPL命令により読み込んだ文字と空白文字を比較し、一致しなければラベルNUMに分岐させたいので、[b]には「JNZ NUM」が入ります。
∴b=ウ:JNZ NUM
〔cについて〕
前述の通り、空白文字とピリオドを読み込んだ場合には SETWD が呼び出されますが、全ての場合に変換処理を行うのではなく、数字列の処理中の場合にだけ行う必要があります。逆に数字列の処理中でない場合は、何も行わず SETWD の呼出し元に戻らなければなりません。コメントにもあるように GR3 は、数字列の処理状態を示すフラグとなっており、0のとき数字列の処理中、-1のとき数字列の処理中ではないことを示します。[c]の直前でGR3の値をもとにフラグレジスタを設定しているので、GR3が0のときには DTOB を呼出し、そうではないときには何の処理も行わずRET命令で呼出し元に戻る処理が適切です。したがって[c]には、GR3 が0以外のときにラベルFIN2に分岐する「JNZ FIN2」が入ります。
∴c=イ:JNZ FIN2
〔dについて〕
[d]の3行前の DTOB 実行後、GR0 には数字列を数値に変換した値が格納されています。次行のST命令で、GR7 が保持するアドレスに GR0 の値を格納しています。GR7 はプログラムの4行目「LD GR7,GR2」で管理テーブルの先頭アドレスが格納されているので、この処理は管理テーブルに数値を追加する操作であることがわかります。管理テーブルは1つのアドレスに1つの数値を格納するので、数値を格納したら格納先のアドレスを1つ後ろに進めておかなければなりません。そうしないと同じアドレスを何度も上書きしてしまうことになります。
よって、GR7 のアドレスを1つ後ろに進める「LAD GR7,1,GR7」が適切です。
なお GR7 を更新している選択肢のうち、「ウ」は2つ目の数値以降、常に先頭アドレスの1つ後ろを更新することになるので誤り、「エ」は常に先頭アドレスを更新することになるので誤りです。
∴d=エ:LAD GR7,1,GR7
設問3
GETWD を使用して,二つの整数の積を求める副プログラム MULT を作成した。プログラム3中の に入れる正しい答えを,解答群の中から選べ。
〔プログラム3の説明〕
〔プログラム3の説明〕
- MULT は,数字列を二つだけ含む,〔プログラム2の説明〕の(1)で示した形式の文字列について,最初の数字列に対応する数値を被乗数とし,2番目の数字列に対応する数値を乗数として乗算を行う。乗算においてあふれは発生しないものとする。
- 主プログラムは,文字列が格納されている領域の先頭アドレスを GR1 に設定し
て,MULT を呼ぶ。MULT は,演算結果を GR0 に格納して呼出し元に戻る。 - 副プログラム MULT から戻るとき,汎用レジスタ GR1~GR7 の内容は元に戻す。
e に関する解答群
- JMI FIN
- JMI NEXT
- JPL FIN
- JPL NEXT
- JZE FIN
- JZE NEXT
f に関する解答群
- ADDL GR0,GR5
- ADDL GR5,GR4
- LD GR5,GR4
- SLL GR5,1
- SRL GR5,1
解答選択欄
- e:
- f:
解答
- e=オ
- f=オ
解説
〔eについて〕
ここでは直前の GR5 の値に基づいて設定されたフラグレジスタの値によって分岐しています。〔プログラム1の説明〕冒頭にあるように、数字列は「0~65534の整数を表す数字から成る文字列」なので GR5 には正の整数または0が格納されているはずです。この時点でJMI命令を使っている「ア」「イ」は不適切であるとわかります。
プログラムを見るとラベルFINに分岐する命令がありません。ここにラベルFINに分岐させる命令がないと永久ループになってしまうので、プログラムを終了させるときの条件が入るとわかります。乗数が正の整数のときには計算処理の対象となりますが、0のときには現在の GR0 の値が計算結果となりますので、JZE命令で GR5 が0のときにラベルFINに分岐させる「オ」が適切です。
∴e=オ:JZE FIN
〔fについて〕
このプログラムでは乗数を最下位から上位に向かって1ビットずつ確認しながら、GR0 に適切な値を加算することで乗算を行っています。例えば、GR4 が12(1100(2))、GR5 が5(101(2))とき、12×5 は次のように処理されます。
∴f=オ:SRL GR5,1
ここでは直前の GR5 の値に基づいて設定されたフラグレジスタの値によって分岐しています。〔プログラム1の説明〕冒頭にあるように、数字列は「0~65534の整数を表す数字から成る文字列」なので GR5 には正の整数または0が格納されているはずです。この時点でJMI命令を使っている「ア」「イ」は不適切であるとわかります。
プログラムを見るとラベルFINに分岐する命令がありません。ここにラベルFINに分岐させる命令がないと永久ループになってしまうので、プログラムを終了させるときの条件が入るとわかります。乗数が正の整数のときには計算処理の対象となりますが、0のときには現在の GR0 の値が計算結果となりますので、JZE命令で GR5 が0のときにラベルFINに分岐させる「オ」が適切です。
∴e=オ:JZE FIN
〔fについて〕
このプログラムでは乗数を最下位から上位に向かって1ビットずつ確認しながら、GR0 に適切な値を加算することで乗算を行っています。例えば、GR4 が12(1100(2))、GR5 が5(101(2))とき、12×5 は次のように処理されます。
- GR5(101)の最下位ビットが1なので、GR0 に GR4 の値を加算(GR0=1100)
- GR4 を1ビット左シフト(GR4=11000)
- GR5 を1ビット右シフト(GR5=10)
- GR5(10)の最下位ビットが0なので、GR4 への加算はなし(GR0=1100)
- GR4 を1ビット左シフト(GR4=110000)
- GR5 を1ビット右シフト(GR5=1)
- GR5(1)の最下位ビットが1なので、GR0 に GR4 の値を加算(GR0=111100)
- GR4 を1ビット左シフト(GR4=1100000)
- GR5 を1ビット右シフト(GR5=0)
- GR5 が0になったのでラベルFINに分岐(GR0=111100)
∴f=オ:SRL GR5,1