HOME»基本情報技術者平成30年秋期問題»午後問12
基本情報技術者過去問題 平成30年秋期 午後問12
⇄問題文と設問を画面2分割で開く⇱問題PDF⇱アセンブラ言語の仕様問12 ソフトウェア開発(アセンブラ)
次のアセンブラプログラムの説明及びプログラムを読んで,設問1,2に答えよ。
〔プログラムの説明〕
1970年1月1日(以下,基準日という)から,指定された日付までの日数を求める副プログラム群である。日付は,全て西暦(グレゴリオ暦)の日付であり,基準日以降でなければならない。
〔プログラムの説明〕
1970年1月1日(以下,基準日という)から,指定された日付までの日数を求める副プログラム群である。日付は,全て西暦(グレゴリオ暦)の日付であり,基準日以降でなければならない。
- プログラム1は,基準日から指定された日付までの日数を計算する副プログラム DAYOFFST である。日付は,GR2 に設定されたアドレスから始まる連続した3語に年,月,日を表す数値でこの順に格納され,誤りはないものとする。基準日を0日目とし,指定された日付までの日数を,符号のない数値(0~65535)として GR0 に設定して呼出し元に戻る。ただし,日付は基準日から65535日目までの日付で与えられる。
- プログラム2は,うるう年を判定する副プログラム LEAPYEAR である。GR2 に設定された年が平年の場合は0を,うるう年の場合は1を,GR0 に設定して呼出し元に戻る。年が平年であるか,うるう年であるかの判定は,次の順に行う。
- 年が4で割り切れない場合,平年とする。
- 年が4で割り切れ,かつ100で割り切れない場合,うるう年とする。
- 年が400で割り切れる場合,うるう年とする。
- ①~③のいずれでも決定しなかった場合,平年とする。
- 副プログラム DIVISIBL は,GR2 に設定された整数値が GR3 に設定された整数値で割り切れる場合は1を,割り切れない場合は0を,GR0 に設定して呼出し元に戻る。プログラムのソースコードは,省略する。
- 各副プログラムから戻るとき,汎用レジスタ GR1~GR7 の内容は元に戻す。
設問1
プログラム中の に入れる正しい答えを,解答群の中から選べ。
a に関する解答群
- LAD GR4,ACCMDAYS
- LAD GR4,ACCMDAYS,GR3
- LAD GR4,ACCMDAYS,GR5
- LD GR4,ACCMDAYS
- LD GR4,ACCMDAYS,GR3
- LD GR4,ACCMDAYS,GR5
b に関する解答群
- JMI BREAK
- JNZ BREAK
- JOV BREAK
- JPL BREAK
- JUMP BREAK
- JZE BREAK
c に関する解答群
- JMI FIN
- JNZ FIN
- JOV FIN
- JUMP FIN
- JZE FIN
d に関する解答群
- AND GR0,=#FFFE
- AND GR0,=1
- OR GR0,=#FFFE
- OR GR0,=1
- XOR GR0,=#FFFE
- XOR GR0,=1
解答選択欄
- a:
- b:
- c:
- d:
解答
- a=イ
- b=カ
- c=イ
- d=カ
解説
〔aについて〕
プログラム開始からラベルLOOPまでの処理は、月・日部分について1月1日を0日目とした日数を GR1 に求める処理です。
まず、6行目で GR1 の日データを1減じています。これは1日を0日目、2日を1日目とカウントするためです。その後、[a]の処理が行われた後、GR1 に GR4 が示す(アドレス-1)番地の値を加算しています。どの選択肢にも月ごとの1月1日からの日数を保持する定数 ACCMDAYS が使われていることを見ると、[a]には月データに応じた経過日数を求めるために必要な処理が入ることがわかります。
GR4 には月ごとに異なる値が入らなければ適切な処理とはならないため、月データが格納されている GR3 を使っていない「ア」「ウ」「エ」「カ」は不適切であることがわかります。残る「イ」と「オ」の違いは LD と LAD です。
仮に GR3 に3が格納されている場合を考えると、LAD命令では GR4 にアドレス ACCMDAYS+3 が格納されます。一方、LD命令では GR4 に ACCMDAYS+3 が示す値(90)が格納されます。8行目では、月が3のときには ACCMDAYS+2 番地が示す値を、月が5のときには ACCMDAYS+4 番地が示す値を、というように ACCMDAYS+月-1 番地が示す値を GR1 に加算したいので、GR4 にはLAD命令を使ってアドレスを格納しておかなければなりません。LD命令で値を格納すると、(値-1)番地を参照することになるので適切な値を加算することができません。
∴a=イ:LAD GR4,ACCMDAYS,GR3
〔bについて〕
15~21行目までのループ処理は、GR2 をループ変数(ループの最後に1加算)として1970年から(年-1)までの間、1年の日数を足し合わせていく処理です。仮に年が2000だったとすると、ループで日数を加算するのは GR2 が1999までの間ということになります。よって、ループの最初で GR2(ループ変数)とGR5(年データ)をCPA命令で比較して、同じ値(ZFが1)であればループを抜けることになります。よって、[b]には「JZE BREAK」が入ります。
∴b=カ:JZE BREAK
〔cについて〕
プログラム LEAPYEAR は GR2 に設定された年が平年であれば GR0 に0を、うるう年であれば1を格納して呼出し元に戻ります。
[c]の直前の処理では、AND演算によって GR2 の値の下位2ビットの値を GR3 に格納しています。これは、プログラム2の①の「年が4で割り切れない場合,平年とする」と判定するための処理です。4で割り切れる数のビット表現を考えてみると、
3行目の処理で GR0 は0で初期化されており、4で割り切れない(平年の)場合にはこのままプログラムを終了させれば良いので、GR3 が0以外、すなわちZFが0のときにラベルFINに分岐させるJNZ命令が適切となります。
∴c=イ:JNZ FIN
〔dについて〕
プログラム2の②の「年が4で割り切れ,かつ100で割り切れない場合,うるう年とする」と判定するための処理です。4で割り切れない場合には[c]でプログラム終了に分岐しているので、ここでは4で割り切れる数について、さらに100で割り切れるかどうかを判定することになります。
8行目の DIVISIBL の呼出しにより、GR2 が100で割り切れる場合には GR0 に1が、割り切れない場合には0が格納されています。うるう年と判定されるのは100で割り切れない場合で、このとき GR0 に1を格納してプログラムを終了させなければならないため、ここでは GR0 のビットを反転する必要があります。GR0 が1になっていれば直後のJNZ命令によりラベルFINに分岐して、呼出し元に戻ります。
ビットを反転するには、反転させたい位置のビットを1としたビットマスクとのXOR演算を行います。0→1、1→0としたいだけなので、GR0 と1をXOR演算する処理が適切です。
∴d=カ:XOR GR0,=1
プログラム開始からラベルLOOPまでの処理は、月・日部分について1月1日を0日目とした日数を GR1 に求める処理です。
まず、6行目で GR1 の日データを1減じています。これは1日を0日目、2日を1日目とカウントするためです。その後、[a]の処理が行われた後、GR1 に GR4 が示す(アドレス-1)番地の値を加算しています。どの選択肢にも月ごとの1月1日からの日数を保持する定数 ACCMDAYS が使われていることを見ると、[a]には月データに応じた経過日数を求めるために必要な処理が入ることがわかります。
GR4 には月ごとに異なる値が入らなければ適切な処理とはならないため、月データが格納されている GR3 を使っていない「ア」「ウ」「エ」「カ」は不適切であることがわかります。残る「イ」と「オ」の違いは LD と LAD です。
仮に GR3 に3が格納されている場合を考えると、LAD命令では GR4 にアドレス ACCMDAYS+3 が格納されます。一方、LD命令では GR4 に ACCMDAYS+3 が示す値(90)が格納されます。8行目では、月が3のときには ACCMDAYS+2 番地が示す値を、月が5のときには ACCMDAYS+4 番地が示す値を、というように ACCMDAYS+月-1 番地が示す値を GR1 に加算したいので、GR4 にはLAD命令を使ってアドレスを格納しておかなければなりません。LD命令で値を格納すると、(値-1)番地を参照することになるので適切な値を加算することができません。
∴a=イ:LAD GR4,ACCMDAYS,GR3
〔bについて〕
15~21行目までのループ処理は、GR2 をループ変数(ループの最後に1加算)として1970年から(年-1)までの間、1年の日数を足し合わせていく処理です。仮に年が2000だったとすると、ループで日数を加算するのは GR2 が1999までの間ということになります。よって、ループの最初で GR2(ループ変数)とGR5(年データ)をCPA命令で比較して、同じ値(ZFが1)であればループを抜けることになります。よって、[b]には「JZE BREAK」が入ります。
∴b=カ:JZE BREAK
〔cについて〕
プログラム LEAPYEAR は GR2 に設定された年が平年であれば GR0 に0を、うるう年であれば1を格納して呼出し元に戻ります。
[c]の直前の処理では、AND演算によって GR2 の値の下位2ビットの値を GR3 に格納しています。これは、プログラム2の①の「年が4で割り切れない場合,平年とする」と判定するための処理です。4で割り切れる数のビット表現を考えてみると、
- 4 → 0100
- 8 → 1000
- 12 → 1100
- 16 → 10000
- 20 → 10100
3行目の処理で GR0 は0で初期化されており、4で割り切れない(平年の)場合にはこのままプログラムを終了させれば良いので、GR3 が0以外、すなわちZFが0のときにラベルFINに分岐させるJNZ命令が適切となります。
∴c=イ:JNZ FIN
〔dについて〕
プログラム2の②の「年が4で割り切れ,かつ100で割り切れない場合,うるう年とする」と判定するための処理です。4で割り切れない場合には[c]でプログラム終了に分岐しているので、ここでは4で割り切れる数について、さらに100で割り切れるかどうかを判定することになります。
8行目の DIVISIBL の呼出しにより、GR2 が100で割り切れる場合には GR0 に1が、割り切れない場合には0が格納されています。うるう年と判定されるのは100で割り切れない場合で、このとき GR0 に1を格納してプログラムを終了させなければならないため、ここでは GR0 のビットを反転する必要があります。GR0 が1になっていれば直後のJNZ命令によりラベルFINに分岐して、呼出し元に戻ります。
ビットを反転するには、反転させたい位置のビットを1としたビットマスクとのXOR演算を行います。0→1、1→0としたいだけなので、GR0 と1をXOR演算する処理が適切です。
∴d=カ:XOR GR0,=1
- GR0 には常に0が格納されるので誤りです。
- GR0 の値は元の値のままなので誤りです。
- GR0 の値は元の値のままなので誤りです。
- GR0 には常に1が格納されるので誤りです。
- GR0 には常に0が格納されるので誤りです。
設問2
次の記述中の に入れる正しい答えを,解答群の中から選べ。
副プログラム DAYOFFST に,基準日から65536日目以降32767年12月31日までの日付を与えた場合には,あふれが発生し,正しい結果を返すことができない。あふれが発生したことを呼出し元に通知するために,フラグレジスタ FR の OF が1の状態で呼出し元に戻るようにしたい。このためには,プログラム1の行番号eの行の直後にf命令を挿入し,ラベル EXIT の行に分岐する必要がある。
副プログラム DAYOFFST に,基準日から65536日目以降32767年12月31日までの日付を与えた場合には,あふれが発生し,正しい結果を返すことができない。あふれが発生したことを呼出し元に通知するために,フラグレジスタ FR の OF が1の状態で呼出し元に戻るようにしたい。このためには,プログラム1の行番号eの行の直後にf命令を挿入し,ラベル EXIT の行に分岐する必要がある。
e に関する解答群
- 8
- 13
- 18
- 19
- 20
f に関する解答群
- JMI
- JNZ
- JOV
- JPL
- JZE
解答選択欄
- e:
- f:
解答
- e=エ
- f=ウ
解説
〔e,fについて〕
本プログラムでは日数を GR1 に加算しているので、GR1が16ビット論理10進数の最大値である65535を超えるとあふれが発生し、正しい結果を返すことができません。
GR1 に加算するタイミングは、8行目、13行目、19行目の3つありますが、8行目、13行目についてはループ処理の前に多くても1回実行されるだけなのであふれは生じません。あふれが生じる可能性があるのは、365または366を加算することを繰り返す19行目の処理です。GR1 に加算を実行した時点であふれが生じたのなら、OFが1になっているはずなので、JOV命令でEXITに分岐させる処理が適切です。
なお、20行目の後だとGR2、つまりループ変数の値に基づいてフラグレジスタが設定されるので、設問の条件にある32767以下であればOFが1になることはありません。
∴e=エ:19
f=ウ:JOV
本プログラムでは日数を GR1 に加算しているので、GR1が16ビット論理10進数の最大値である65535を超えるとあふれが発生し、正しい結果を返すことができません。
GR1 に加算するタイミングは、8行目、13行目、19行目の3つありますが、8行目、13行目についてはループ処理の前に多くても1回実行されるだけなのであふれは生じません。あふれが生じる可能性があるのは、365または366を加算することを繰り返す19行目の処理です。GR1 に加算を実行した時点であふれが生じたのなら、OFが1になっているはずなので、JOV命令でEXITに分岐させる処理が適切です。
なお、20行目の後だとGR2、つまりループ変数の値に基づいてフラグレジスタが設定されるので、設問の条件にある32767以下であればOFが1になることはありません。
∴e=エ:19
f=ウ:JOV