戦国IT - 情報処理技術者試験の過去問対策サイト
ブログお知らせお問い合わせ料金プラン

基本情報技術者 2018年 秋期 午後 問12


次のアセンブラプログラムの説明及びプログラムを読んで、設問1,2に答えよ。

〔プログラムの説明〕  1970年1月1日(以下、基準日という)から、指定された日付までの日数を求める副プログラム群である。日付は、全て西暦(グレゴリオ暦)の日付であり、基準日以降でなければならない。
(1) プログラム1は、基準日から指定された日付までの日数を計算する副プログラムDAYOFFSTである。日付は、GR2に設定されたアドレスから始まる連続した3語に年、月、日を表す数値でこの順に格納され、誤りはないものとする。基準日を0日目とし、指定された日付までの日数を、符号のない数値(0~65535)としてGR0に設定して呼出し元に戻る。ただし、日付は基準日から65535日目までの日付で与えられる。 (2) プログラム2は、うるう年を判定する副プログラムLEAPYEARである。GR2に設定された年が平年の場合は0を、うるう年の場合は1を、GR0に設定して呼出し元に戻る。年が平年であるか、うるう年であるかの判定は、次の順に行う。  ① 年が4で割り切れない場合、平年とする。  ② 年が4で割り切れ、かつ100で割り切れない場合、うるう年とする。  ③ 年が400で割り切れる場合、うるう年とする。  ④ ①〜③のいずれでも決定しなかった場合、平年とする。 (3) 副プログラムDIVISIBLは、GR2に設定された整数値がGR3に設定された整数値で割り切れる場合は1を、割り切れない場合は0を、GR0に設定して呼出し元に戻る。プログラムのソースコードは、省略する。 (4) 各副プログラムから戻るとき、汎用レジスタGR1〜GR7の内容は元に戻す。
基本情報技術者試験(平成30年 午後 問12 プログラム1)
基本情報技術者試験(平成30年 午後 問12 プログラム2)

設問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:カ

解説

解答の導き方

DAYOFFSTは、指定された日付までの日数を「その年の1月1日からの日数」と「それより前の年の日数」に分けて計算します。プログラムでは、GR0などのGRは汎用レジスタ(General Register:計算中の値を一時的に置く場所)を表します。
a:月に応じた日数を表から取り出す準備
GR3には月、GR1には日が入ります。6行目でGR1から1を引くのは、1日を「その月の0日目」として扱うためです。
ACCMDAYSには、平年の各月の1日が、1月1日から何日後かを並べています。たとえば、1月の値は0、2月の値は31です。月を表すGR3は1から始まりますが、表の位置は0から始まります。そのため、必要な位置は「GR3から1を引いた位置」です。
ここでGR4には、表の先頭アドレスにGR3を加えたアドレスを設定します。LAD(Load Address:アドレスを設定する命令)は、データそのものではなく、データの置き場所をGR4に設定します。その後の「ADDL GR1,-1,GR4」では、GR4から1を引いた位置にある表の値をGR1に加えます。結果として、月に対応する「1月1日からの日数」が加算されます。
したがって、GR4を「表の先頭アドレス+GR3」にする「LAD GR4,ACCMDAYS,GR3」が必要です。aはイです。
b:指定された年より前の年だけを加算する
14行目でGR2に1970を設定し、15行目の「CPA GR2,GR5」で、現在の年GR2と指定された年GR5を比べます。
ループでは、現在の年について平年の日数365を加え、うるう年ならさらに1を加えます。そのあとGR2を1増やし、次の年を調べます。つまり、加算するのは1970年から「指定された年の1年前」までです。指定された年そのものの日数は、後で月と日の計算に含めます。
そのため、GR2とGR5が等しくなった時点でループを終える必要があります。CPAで比べた結果が等しいときに分岐する命令はJZEです。よって、bはカです。
c:4で割り切れない年を判定する
3行目の「SUBA GR0,GR0」でGR0を0にしています。平年の場合はこの値のまま戻り、うるう年の場合は後の処理で1になります。
5行目の「AND GR3,=3」は、年の下位2ビットを調べます。AND(論理積)は、両方の値でビットが1になっている部分を取り出す処理です。4で割り切れる数は2進数で下位2ビットが00になるため、この処理の結果が0になります。4で割り切れない数は結果が0以外になります。
結果が0以外なら、その年は4で割り切れません。うるう年ではないので、GR0を0のままにしてFINへ進みます。したがって、0以外のときにFINへ分岐する「JNZ FIN」が必要です。cはイです。
d:100で割り切れる年は、400での判定に進む
DIVISIBLは、割り切れる場合にGR0を1、割り切れない場合に0にします。したがって、100で割り切れるかを調べた直後のGR0は、次のようになります。
100で割り切れるかDIVISIBL後のGR0
割り切れない0
割り切れる1
年が100で割り切れない場合は、うるう年としてGR0を1にして終了します。一方、100で割り切れる場合は、400で割り切れるかを続けて調べます。
そこで、GR0が0と1のどちらであっても反転させます。XOR(exclusive OR:排他的論理和)で1との演算を行うと、0は1に、1は0になります。
XORの前のGR0XOR後のGR0次の処理
01JNZ FINで終了
10400で割り切れるかを調べる
この動きになるのは「XOR GR0,=1」です。dはカです。400で割り切れるかを調べた後は、DIVISIBLが設定したGR0の値をそのまま判定結果として戻します。

誤りやすいポイント

  • LADとLDを取り違えないようにします。LADはデータの置き場所を設定し、LDはその場所にあるデータを読み込みます。aでは、後の命令で表の値を使うためのアドレスを作るのでLADが必要です。
  • 月は1から始まりますが、表の位置は0から始まります。月に対応する表の位置は、GR3から1を引いた位置です。
  • bのJZEは、GR0が0かどうかではなく、直前のCPAによる比較結果が等しいかどうかで分岐します。
  • 100で割り切れる年は、その時点で平年と決まるわけではありません。400でも割り切れる場合はうるう年です。dでは、100で割り切れない場合だけ先に終了するようにGR0を反転させています。

FAQ

Q: 1日から1を引くのはなぜですか?
A: 1月1日を、その月の0日目として数えるためです。たとえば、1月1日なら日による加算は0、1月2日なら1になります。
Q: うるう年の1日を月の計算に加えるのは、なぜ3月以降なのですか?
A: うるう年で増える日は2月29日です。2月までの日数にはまだ加えず、3月以降の日付を計算するときに加える必要があるためです。
Q: 100で割り切れるかを調べた後、なぜGR0を反転させるのですか?
A: 100で割り切れない場合は、うるう年としてすぐ終了します。100で割り切れる場合だけ400での判定に進む必要があるため、DIVISIBLの結果を反転させてJNZの分岐条件に合わせています。

関連キーワード: アセンブリ言語、汎用レジスタ、インデックス修飾、論理積、排他的論理和、うるう年判定

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

 次の記述中のに入れる正しい答えを、解答群の中から選べ。    副プログラム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:ウ

解説

解答の導き方

この設問では、計算結果が扱える範囲を超えたことを、どの行の直後で、どの命令を使って検出するかを考えます。
まず、問題文には、日数を「符号のない数値(0~65535)」としてGR0に設定するとあります。符号のない数値では、負の値を表すための場所を使わず、数値を表します。そのため、扱える最大値は65535です。基準日を0日目とするので、65535日目までは範囲内ですが、65536日目以降は範囲を超えます。
次に、DAYOFFSTで日数を計算する流れを見ます。
  • 行番号6で、日付の日の値から1を引きます。
  • 行番号8では、月に応じた日数を加えます。行番号13では、うるう年で3月以降の場合に1日を加えます。ここまでで、指定された年の1月1日からの日数を求めます。
  • 行番号18では、GR0に1年分の日数を設定します。LEAPYEARの判定結果に応じて、平年なら365、うるう年なら366になります。
  • 行番号19では、その1年分の日数を、それまでの合計であるGR1に加えます。
GR1は、日付までの日数を計算している汎用レジスタ(General Register:計算途中の値を置くレジスタ)です。年ごとの日数をGR1に加えていく途中で、合計が65535を超える可能性があります。
符号なしの加算命令ADDLは、計算結果が表せる範囲を超えると、FR(Flag Register:演算結果の状態を記録するレジスタ)のOF(Overflow Flag:桁あふれを示すフラグ)を1にします。したがって、桁あふれを検出するには、合計を更新する行番号19の直後でOFを確認します。
OFが1のときに分岐する命令はJOVです。そのため、行番号19の直後にJOV EXITを挿入すれば、桁あふれが起きた場合にEXITへ進めます。判定を直後に行うのは、後続の演算命令によってOFの状態が変わる可能性があるためです。

誤りやすいポイント

  • 行番号18ではなく、行番号19の直後を選びます。行番号18でGR0に設定するのは1年分の365または366だけです。日数の合計であるGR1に加算するのは行番号19です。
  • 65535日目もあふれる、と考えないようにします。65535は扱える最大値で、範囲を超えるのは65536日目からです。
  • JNZは「結果が0ではないとき」の分岐であり、桁あふれの判定には使えません。JMIやJPLは符号に関する判定なので、符号なしの数値の範囲超過を調べる目的とは異なります。
  • 桁あふれが起きたら、結果をGR0に移す処理を通らずEXITへ分岐します。これにより、あふれた値を正常な計算結果として返す処理を避けられます。

FAQ

Q: 65536日目を加算すると、GR1には何が入りますか?
A: 16ビットで表せる範囲を超えるため、GR1には下位の値が残り、OFが1になります。OFを確認すれば、GR1の値だけでは分からない桁あふれを検出できます。
Q: なぜJNZではなくJOVを使うのですか?
A: あふれた結果が0になるとは限りません。JNZは結果が0かどうかを調べますが、JOVはOFが1かどうかを調べるため、桁あふれの検出に適しています。
Q: EXITへ分岐すると、どのように呼出し元へ戻りますか?
A: EXITの行でGR1~GR7を元の内容に戻し、その後RETで呼出し元へ戻ります。あふれた結果をGR0に設定する処理は通りません。

関連キーワード: 符号なし整数、オーバーフロー、フラグレジスタ、条件分岐、加算命令

解説を読んでも分からないところは、AIに質問できます。 この問題の本文と解説をふまえて答えます。

この設問をAIに質問する

クイズモードで開きます(AIへの質問は無料の会員登録で使えます)

戦国ITクイズ機能

\ せっかくなら /

基本情報技術者を
クイズ形式で学習しませんか?

クイズ画面へ遷移する→

すぐに利用可能!

©︎2026 情報処理技術者試験対策アプリ

このサイトについてブログプライバシーポリシー利用規約特商法表記開発者について