[過去問を解いていく] - [基本情報技術者過去問題] - [令和元年秋期] - [午後問8(データ構造及びアルゴリズム)]

過去問を解いていく

令和元年秋期

設問

設問1

設問1-a

「設問1-a」は、 検索文字列が“ACABAB”(図1)の時に、図2の[ a ]に格納されるビット列を答える問題です。


文字列中の’A’と’C’について、図2に格納された’A’および’C’のビットマスク値との関係を下表に示します。

文字列 ビットマスク値
A_A_A_ 0・・・010101
_C____ 0・・・000010

この表から、「文字列の左側からの並び」と「ビットマスク値の右側からの並び」とが対応していることが解ります。

’B’は、検索文字列“ACABAB”の左から4番目と6番目に存在しているので、ビットマスク値の右側から4番目と6番目が1となる、「イ. 0000000000101000」が正解となります。

ここで、推測できなくても問題ありません。
[ c ]に関する解答群を解く時にヒントが得られます。
設問1-a 再考参照


設問1-b,c

「設問1-b,c」は、 〔プログラム1〕中の穴埋め箇所に当てはまる処理を答える問題です。


記述抽出

本プログラムの処理詳細は、〔プログラムの説明〕の中に、以下のように記述されています。

 関数 GenerateBitMask は、Mask[] の全ての要素を“0”Bに初期化した後、
1以上で Pat[] の文字数以下の全てのiに対して、Pat[i] の文字に対応する Mask[] の要素である Mask[Index(Pat[i])] に格納されている値の、下位から数えてi番目のビットの値を1にする。


対応付け

プログラムの処理詳細の記述を解析し、プログラムと対応付けします。

• PatLen ← Pat[] の文字数 

本処理の記述説明なし

■ i : 1, i ≦ 26, 1. 
|• Mask[i] ← [ b ]       /* 初期化 */ 

Mask[] の全ての要素を“0”Bに初期化

■ i: 1, i ≦ PatLen, 1 
|• Mask[Index(Pat[i])] ← [ c ]と
|                 Mask[Index(Pat[i])] とのビットごとの論理和 

1以上で Pat[] の文字数以下の全てのiに対して、Pat[i] の文字に対応する Mask[] の要素である Mask[Index(Pat[i])] に格納されている値の、下位から数えてi番目のビットの値を1にする。

• return (PatLen) 

本処理の記述説明なし


[ b ]について記述からの推定

プログラムの処理詳細の記述に適した処理を解答群から選び出します。

■ i : 1, i ≦ 26, 1. 
|• Mask[i] ← [ b ]       /* 初期化 */ 

Mask[] の全ての要素を“0”Bに初期化

プログラムの処理詳細の記述に「“0”Bに初期化」と記述されているので、「ア. “0”B」が正解候補となります。


[ b ]についてプログラムからの推定

解答群から選択した処理をプログラムに適用し、矛盾がないことを確認します。

「ア. “0”B」を適用することで「Mask[] の全ての要素を“0”Bに初期化」できるので、「ア. “0”B」が正解となります。


[ c ]について記述からの推定

プログラムの処理詳細の記述に適した処理を解答群から選び出します。

■ i: 1, i ≦ PatLen, 1 
|• Mask[Index(Pat[i])] ← [ c ]と
|                 Mask[Index(Pat[i])] とのビットごとの論理和 

1以上で Pat[] の文字数以下の全てのiに対して、Pat[i] の文字に対応する Mask[] の要素である Mask[Index(Pat[i])] に格納されている値の、下位から数えてi番目のビットの値を1にする。

理解力のある方ならこの記述内容を理解できるのでしょうが、残念ながら、私には理解できませんでした。 設問1-c 再考参照

そこで、プログラムから推定することとします。


[ c ]についてプログラムからの推定

解答群の各処理をプログラムに適用し、矛盾がないかを確認します。
 (注:PatLenの値が6と仮定し、トレースします。)

オ.

Mask[Index(Pat[i])] ← “1”B OR Mask[Index(Pat[i])]

Mask[]の各要素(Mask[1]~Mask[26])に対し、“1”Bのみが設定されるので誤りとなります。

ウ.

Mask[Index(Pat[i])] ← “100000”B OR Mask[Index(Pat[i])]

Mask[]の各要素(Mask[1]~Mask[26])に対し、“100000”Bのみが設定されるので誤りとなります。

エ.

Mask[Index(Pat[i])] ← “1000000”B OR Mask[Index(Pat[i])]

Mask[]の各要素(Mask[1]~Mask[26])に対し、“1000000”Bのみが設定されるので誤りとなります。

イ.

Mask[Index(Pat[i])] ← 1をiビットだけ論理左シフト OR Mask[Index(Pat[i])]

iは1以上なので最下位ビットをセットできません。よって、誤りとなります。


以上から、イ~オは除外され、「ア. “1”Bを(i-1)ビットだけ論理左シフトした値」が正解となります。

設問1-a 再考

「設問1-c」より、Mask[]には「“1”Bを(i-1)ビットだけ論理左シフトした値」が格納されることが分かりました。

文字列が“ACABAB”の時’B’は4文字目と6文字目に存在するので、

  • 「“1”Bを(4-1)ビットだけ論理左シフトした値」
  • 「“1”Bを(6-1)ビットだけ論理左シフトした値」

がセットされた、“101000”Bが Mask[2] に格納されます。

設問1-c 再考

プログラムの処理詳細の記述をプログラムに対応付けしやすいように、プログラムを書き換えてみます。

書き換え前

■ i: 1, i ≦ PatLen, 1 
|• Mask[Index(Pat[i])] ← [ c ]と
|                 Mask[Index(Pat[i])] とのビットごとの論理和 

書き換え後

■ i: 1, i ≦ PatLen, 1 
|• k ← Pat[i]         /*検索文字列から1文字取得*/
|• n ← Index(k)       /*取得した文字のインデックス取得*/
|• x ← Mask[n]        /*更新対象のマスク値を取得*/
|• y ← [ c ]        /*マスク値にセットするビット列を生成*/
|• Mask[n] ← x OR y  /*Mask[]の反映*/

[ c ]の答えが分かった上で、プログラムの処理詳細の記述を解析し、プログラムと対応付けしてみます。

■ i: 1, i ≦ PatLen, 1 

1以上で Pat[] の文字数以下の全てのiに対して、

|• k ← Pat[i]       

Pat[i] の文字

|• n ← Index(k)     

Pat[i] の文字に対応する

|• x ← Mask[n]

Pat[i] の文字に対応する Mask[] の要素である Mask[Index(Pat[i])] に格納されている値

|• y ← [ c ]

下位から数えてi番目のビットの値を1

|• Mask[n] ← x OR y

Pat[i] の文字に対応する Mask[] の要素である Mask[Index(Pat[i])] に格納されている値


プログラムの処理詳細の記述にある「下位から数えてi番目のビットの値を1」が、「ア. “1”Bを(i-1)ビットだけ論理左シフトした値」に対応しているようです。

設問2

設問2-d,e,f

「設問2-d,e,f」は、 図1の状態で、プログラム2を実行し、行βを実行した直後の内部変数値を問う問題です。
 プログラムの処理詳細は記述されていないので、地道にトレースを行っていきます。


トレース

[ d ]を求めるにあたっては、下記の記事を参考に地道にトレースしてみます。

 例えば、iが1のときに行βを実行した直後の Status の値は“1”Bであることから、
iが2のときに行αを実行した直後の Status の値は、“1”Bを1ビットだけ論理左シフトした“10”Bと“1”Bとのビットごとの論理和を取った“11”Bとなる。
 次に、iが2のときに行βを実行した直後の Status の値は、Mask[Index(Text[2])] の値が“10101”Bであることを考慮すると、[ d ]となる。

i=1の時

  • i=1の時、対象文字列の1文字目(‘A’)が取り出され、’A’のマスク値であるMask[1]が参照されます。
  • Mask[1]に設定されている値は、“10101”Bです。
Status値
α実行前 “0”B
α実行後 “1”B ← “0<<1” or “1”B
β実行後 “1”B ← “1”B and “10101”B
行βを実行した直後の Status の値は“1”Bであることから、

i=2の時

  • i=2の時、対象文字列の1文字目(‘A’)が取り出され、’A’のマスク値であるMask[1]が参照されます。
  • Mask[1]に設定されている値は、“10101”Bです。
Status値
α実行前 “1”B
α実行後 “11”B ← “1<<1” or “1”B
行αを実行した直後の Status の値は、“1”Bを1ビットだけ論理左シフトした“10”Bと“1”Bとのビットごとの論理和を取った“11”Bとなる。
β実行後 “1”B ← “11”B and “10101”B
行βを実行した直後の Status の値は、Mask[Index(Text[2])] の値が“10101”Bであることを考慮すると、[ d ]となる。

以上のトレースの結果、[ d ]は、「イ.“1”B 」が正解となります。


i=9の時

  • i=9の時、対象文字列の1文字目(‘A’)が取り出され、’A’のマスク値であるMask[1]が参照されます。
  • Mask[1]に設定されている値は、“10101”Bです。

よって、[ e ]は、「キ.“10101”B 」が正解となります。


[ f ]を求めるにあたっても、下記の記事を参考に地道にトレースしてみます。

iが8のときに行βを実行した直後の Status の値が“10”Bであるということに留意すると、
iが9のときに行αを実行した直後の行βで参照する Mask[Index(Text[9])] の値は[ e ]であるので、
行βを実行した直後の Status の値は[ f ]となる。

Status値
α実行前 “10”B
iが8のときに行βを実行した直後の Status の値が“10”Bであるということに留意すると
α実行後 “101”B ← “10<<1” or “1”B
“10”Bを1ビットだけ論理左シフトした“100”Bと“1”Bとのビットごとの論理和を取った“101”Bとなる。
β実行後 “101”B ← “101”B and “10101”B
行βを実行した直後の Status の値は[ f ]となる。

以上のトレースの結果、[ f ]は、「カ.“101”B 」が正解となります。

設問3

「設問3-g,h,i」は、 関数 GenerateBitMask を拡張し、関数 GenerateBitMaskRegex を作成した時の Mask[]配列の作られ方を問う問題です。

設問3-g

プログラム2〕のトレースでMask[]の使われ方を理解できていたら、〔プログラム3〕をトレースすることなく、問題を解くことができます。

〔プログラム2〕では、’A’の文字を検出したなら、’A’のマスク値 Mask[1]を参照し、文字位置に対応するビットがONかどうかで判断しています。
 Mask[1]に設定されるマスク値は、’A’の存在する文字位置(1,3,4,5および6番目)に対応するビットがONとなればよいので、マスク値は“111101”Bとなります。
 よって、[ g ]は「カ. “111101”B」が正解となります。

同様に、‘B’,‘C’に着目すると、’B’,’C’のマスク値は下表のようになります。

着目文字 着目文字列 マスク値
‘A’ “A_AAAA” “111101”B
‘B’ "__B_B_" “010100”B
‘C’ "_C__C_" “010010”B
設問3-h

表4の説明にあるように、[]内の文字は1文字として扱われるので、“AC[BA]A[ABC]A”は6文字として扱われます。
 よって、[ h ]は「イ. 6」が正解となります。

プログラムをトレースすると、以下の条件時に文字数が+1されています。

  • ’[’検出時 (2箇所)
  • ’[]’外(Mode=0)で文字を検出した時 (4箇所)
設問3-i

“AC[B[AB]AC]A”のように入れ子になっている場合、どのように扱えばいいのか定義されていないので、プログラムをトレースします。
 全ロジックをトレースする必要はなく、

  • “[”検出中に“[”を検出した場合
  • “]”検出後に再度“]”を検出した場合

の処理をトレースします。

■ i: 1, ≦ OriginalPatLen, 1
|▲ Pat[i] = "["          /*開始検出*/
||• Mode ← 1            /*モードセット*/
||• PatLen ← PatLen + 1 /*"["から"]"までの文字数を1と扱う*/
|----  
||▲ Pat[i] = "]"        /*終了検出*/
|||• Mode ← 0          /*モードクリア*/
||----               /*開始/終了以外*/
|||▲ Mode = 0          /*"["から"]"までの文字をカウントアップしないことで左シフト数を同じくする*/
||||• PatLen ← PatLen + 1
|||▼
|||• Mask[Index(Pat[i])] ← "1"Bを(PatLen - 1)ビットだけ
|||    論理左シフトした値とMask[Index(Pat[i])]とのビットごとの論理和
||▼
|▼

(注:本プログラムは、“[[”と連続した場合を考慮されていません。)

"“[”検出中に“[”を検出した場合

“[”検出 Mode ← 1
PatLen ← PatLen + 1

論理左シフト数更新
’A’検出 Mask[]更新
“[”検出 Mode ← 1
PatLen ← PatLen + 1

論理左シフト数更新

“[”検出中に“["を検出した場合、"][”を検出したような処理となります。

“]”検出後に再度“]”を検出した場合

“]”検出 Mode ← 0
’A’検出 PatLen ← PatLen + 1
Mask[]更新
論理左シフト数更新
“]”検出 Mode ← 0 既にMode=0

“]”が連続した場合、最初の“]”でMode=0になり、後続の“]”でもMode=0としています。


以上より、“AC[B[AB]AC]A”は“AC[B][AB]ACA”と扱われ、
 Mask[1]に設定されるマスク値は、’A’の存在する文字位置(1,4,5および7番目)に対応するビットがONとなればよいので、マスク値は“1011001”Bとなります。

[ i ]は「ウ. “1011001”B」が正解となります。

本文

次のプログラムの説明及びプログラムを読んで、設問1~3に答えよ。

〔プログラムの説明〕

関数 BitapMatch は、Bitap法を使って文字列検索を行うプログラムである。
Bitap法は、検索対象の文字列(以下、対象文字列という)と検索文字列の照合に、個別の文字ごとに定義されるビット列を用いるという特徴をもつ。
なお、本問では、例えば2進数の16ビット論理型の定数 0000000000010101 は、上位の0を省略して“10101”Bと表記する。

  1.  関数 BitapMatch は、対象文字列を Text[] に、検索文字列を Pat[] に格納して呼び出す。配列の要素番号は1から始まり、Text[] のi番目の文字は Text[i] と表記する。Pat[] についても同様にi番目の文字は Pat[i] と表記する。対象文字列と検索文字列は、英大文字で構成され、いずれも最長16文字とする。
    対象文字列 Text[] が“AACBBAACABABAB”、検索文字列 Pat[] が“ACABAB”の場合の格納例を、図1に示す。


  1.  関数 BitapMatch は、関数 GenerateBitMask を呼び出す。 関数 GenerateBitMask は、文字“A”~“Z”の文字ごとに、検索文字列に応じたビット列(以下、ビットマスクという)を生成し、要素数26の16ビット論理型配列 Mask[] に格納する。Mask[1] には文字“A”に対するビットマスクを、Mask[2] には文字“B”に対するビットマスクを格納する。このように Mask[1]~Mask[26] に文字“A”~“Z”に対応するビットマスクを格納する。
    関数 GenerateBitMask は、Mask[] の全ての要素を“0”Bに初期化した後、1以上で Pat[] の文字数以下の全てのiに対して、Pat[i] の文字に対応する Mask[] の要素である Mask[Index(Pat[i])] に格納されている値の、下位から数えてi番目のビットの値を1にする。
    関数 Index は、引数にアルファベット順でn番目の英大文字を設定して呼び出すと、整数n(1≦n≦26)を返す。

  2.  図1で示した、Pat[] が“ACABAB”の例の場合、関数 GenerateBitMask を実行すると、Mask[] は図2のとおりになる。


  1.  関数 GenerateBitMask の引数と返却値の仕様は、表1のとおりである。


〔プログラム1〕

○整数型関数 : GenerateBitMask(文字型: Pat[], 16 ビット論理型: Mask[]) 
○整数型: i, PatLen

• PatLen ← Pat[] の文字数 
■ i : 1, i ≦ 26, 1. 
|• Mask[i] ← [ b ]       /* 初期化 */ 

■ i: 1, i ≦ PatLen, 1 
|• Mask[Index(Pat[i])] ← [ c ]と
|                 Mask[Index(Pat[i])] とのビットごとの論理和 

• return (PatLen) 

設問1

プログラムの説明及びプログラム1中の [  ] に入れる正しい答えを、解答群の中から選べ。

a に関する解答群

  1. 0000000000000101
  2. 0000000000101000
  3. 0001010000000000
  4. 1010000000000000

b に関する解答群

  1. “0”B
  2. “1”B
  3. “1”BをPatLenビットだけ論理左シフトした値
  4. “1”Bを(PatLen-1)ビットだけ論理左シフトした値
  5. “1111111111111111”B

c に関する解答群

  1. “1”Bを(i-1)ビットだけ論理左シフトした値
  2. “1”Bをiビットだけ論理左シフトした値
  3. “1”Bを(PatLen-1)ビットだけ論理左シフトした値
  4. “1”BをPatLen ビットだけ論理左シフトした値
  5. “1”B

〔関数 BitapMatch の説明〕

  1.  Text[] と Pat[] を受け取り、Text[] の要素番号の小さい方から Pat[] と一致する文字列を検索し、見つかった場合は、一致した文字列の先頭の文字に対応する Text[] の要素の要素番号を返し、見つからなかった場合は、-1を返す。
  2.  図1の例では、Text[7]~Text[12] の文字列が Pat[] と一致するので、7を返す。
  3.  関数 BitapMatch の引数と返却値の仕様は、表2のとおりである。


〔プログラム2〕

○整数型関数 : BitapMatch(文字型: Text[], 文字型: Pat[])  
○16 ビット論理型: Goal, Status, Mask[26]  
○整数型: i, TextLen, Pathen  
• TextLen ← Text[] の文字数  
• Pathen ← GenerateBitMask(Pat[], Mask[])  
• Status ← "0"B  
• Goal ← "1"B を (Pathen - 1) ビットだけ論理左シフトした値  
■ i: 1, i ≤ TextLen, 1  
|• Status ← Status を 1ビットだけ論理左シフトした値と               ←α  
|                              "1"B とのビットごとの論理和  
|• Status ← Status と Mask[Index(Text[i])] とのビットごとの論理積 ←β  
|▲Status と Goal とのビットごとの論理積 ≠ "0"B  
||• return(i - PatLen + 1)  
|▼  

• return (-1)  

設問2

次の記述中の [  ] に入れる正しい答えを、解答群の中から選べ。

図1で示したとおりに、Text[] と Pat[] に値を格納し、関数 BitapMatch を実行した。プログラム2の 行β を実行した直後の変数iと配列要素 Mask[Index(Text[i])] と変数 Status の値の遷移は、表3のとおりである。
例えば、iが1のときに 行β を実行した直後の Status の値は“1”Bであることから、iが2のときに 行α を実行した直後の Status の値は、“1”Bを1ビットだけ論理左シフトした“10”Bと“1”Bとのビットごとの論理和を取った“11”Bとなる。次に、iが2のときに 行β を実行した直後の Status の値は、Mask[Index(Text[2])] の値が“10101”Bであることを考慮すると、dとなる。
同様に、iが8のときに 行β を実行した直後の Status の値が“10”Bであるということに留意すると、iが9のときに 行α を実行した直後の 行β で参照する Mask[Index(Text[9])] の値は [ e ] であるので、 行β を実行した直後の Status の値は [ f ] となる。


d、e、f に関する解答群

  1. “0”B
  2. “1”B
  3. “10”B
  4. “11”B
  5. “100”B
  6. “101”B
  7. “10101”B

設問3

関数 GenerateBitMask の拡張に関する、次の記述中の [  ] に入れる正しい答えを、解答群の中から選べ。ここで、プログラム3中の [ b ] には、設問1の [ b ] の正しい答えが入っているものとする。

表4に示すような正規表現を検索文字列に指定できるように、関数 GenerateBitMask を拡張し、関数 GenerateBitMaskRegex を作成した。


〔プログラム3〕

○整数型関数 : GenerateBitMaskRegex(文字型: Pat[],
                         16 ビット論理型: Mask[])
○整数型 : i, OriginalPatLen, PatLen, Mode

• OriginalPatLen ← Pat[] の文字数
• PatLen ← 0 
• Mode ← 0
■ i: 1, ≦ 26, 1
|• Mask[i] ← [ b ]  /*初期化*/

■ i: 1, ≦ OriginalPatLen, 1
|▲ Pat[i] = "["
||• Mode ← 1
||• PatLen ← PatLen + 1
|----  
||▲ Pat[i] = "]"
|||• Mode ← 0
||----  
|||▲ Mode = 0
||||• PatLen ← PatLen + 1
|||▼
|||• Mask[Index(Pat[i])] ← "1"Bを(PatLen - 1)ビットだけ
|||    論理左シフトした値とMask[Index(Pat[i])]とのビットごとの論理和
||▼
|▼

• return (PatLen)

Pat[] に“AC[BA]A[ABC]A”を格納して、関数 GenerateBitMaskRegex を呼び出した場合を考える。この場合、文字“A”に対応するビットマスクである Mask[1] は [ g ] となり、関数 GenerateBitMaskRegex の返却値は [ h ] となる。また、Pat[] に格納する文字列中において[]を入れ子にすることはできないが、誤って Pat[] に“AC[B[AB]AC]A”を格納して関数 GenerateBitMaskRegex を呼び出した場合、Mask[1]は [ i ] となる。

g、i に関する解答群

  1. “1001101”B
  2. “1010100001”B
  3. “1011001”B
  4. “101111”B
  5. “110011”B
  6. “111101”B

h に関する解答群

  1. 4
  2. 6
  3. 9
  4. 13

「最強のCASL2/COMET2環境」の利用方法(メモ)

最強のCASL2/COMET2環境 にて、しゃれたエディタが紹介されています。
記事を読んでいくと、デバッガも使えるよう。

  1. Visual Studio Codeをインストール
  2. CASL2/COMET2拡張機能をインストール
  3. 以上
とのこと。

エディタは使えたが、デバッガはうまく動作せず。
いろいろ試行錯誤して、なんとなく動くようになったので、その方法を紹介します。
(ただ、まだ、PPUSHがうまく動かないなどいくつかの挙動不審があるので、完成形ではないので、ご注意を)

なんとなく動くまでの手順

## CASL2/COMET2 on VSCODE {-}

Visual Studio Codeに、CASL2/COMET2シュミレータを構築する手順を紹介します。

### 環境構築手順 {-}

#### 製品の入手 {-}

1. Node.jsを入手します。

> https://nodejs.org/ja/

2. Visual Studio Codeを入手します。

> https://code.visualstudio.com/download

#### 製品のイントール {-}

1. Node.js のイントール

2. Visual Studio Codeをインストール

#### Visual Studio Codeの日本語化 {-}

1. Visual Studio Codeに下記の拡張機能をインストールします。

> Japanese Language Pack for VS Code

#### TypeScript環境構築 {-}

1. [ファイル]タブの[フォルダを開く]にて、フォルダを選択します。

2. [表示]タブの[ターミナル]にて、ターミナルを開きます。

3. "node"と"npm"のインストール状態を確認します。

> $ node -v
> $ npm -v

4. Package.jsonの生成(問い合わせに対し、デフォルト設定のままでも問題ありません。)

> $ npm init

5. TypeScriptのインストール

> $ npm install -g typescript

6. tsconfig.jsonの生成

> $ npx tsc --init

7. tsconfig.json編集し、デバッガでのブレークを有効とします。

> // "sourceMap": true, → "sourceMap": true,

#### CASL2/COMET2のインストール {-}

1. [表示]タブの[拡張機能]にて、拡張機能をインストールします。
    
> CASL2/COMET2

2. launch.jsonの生成

    [表示]タブの[実行]-[launch.jsonファイルを作成します]-[COMET2 Debug]をクリックします。

3. launch.jsonの編集(任意)

"launch.json"の"casl2Options"の設定を下記を参考に変更します。
https://marketplace.visualstudio.com/items?itemName=MaxfieldWalker.vscode-casl2-comet2

4. settings.json編集(任意)

"settings.json"の"casl2"の設定を下記を参考に変更します。
https://marketplace.visualstudio.com/items?itemName=MaxfieldWalker.vscode-casl2-comet2

"settings.json"は、[左下の歯車]-[設定]から変更できます。

#### CASL2 CLI {-}

https://github.com/node-casl2-comet2/node-casl2
のインストール手順に従います。 

#### node-comet2 {-}

https://github.com/node-casl2-comet2/node-comet2
のインストール手順に従います。 


令和元年秋期 アセンブラ

令和元年秋期


設問1-a

穴埋め部分

03          ST   GR1,A       
06          [  a  ]          
07          ST   GR1,RESULT  ;符号部を退避

解答群

ア AND GR1,=#000F
イ AND GR1,=#F000
ウ AND GR1,=#FFFF
エ OR  GR1,=#000F
オ OR  GR1,=#F000
カ OR  GR1,=#FFFF

正解

ア AND GR1,=#000F

解答方法

次ステップのコメント「符号部を退避」に着目します。
「符号部」をRESULTに格納できる命令は「ア AND GR1,=#000F」だけですので、「ア」が正解となります。

解答群の解説

ア AND GR1,=#000F
GR1に#246Cが設定されている状態で本命令を実行すると、GR1は#000Cとなり、符号部を取り出せます。
イ AND GR1,=#F000
GR1に#246Cが設定されている状態で本命令を実行すると、GR1は#2000となり、符号部が0クリアされてしまいます。
ウ AND GR1,=#FFFF
何も変化しません。
無意味な命令です。
エ OR GR1,=#000F
GR1に#246Cが設定されている状態で本命令を実行すると、GR1は#246Fとなり、破壊されてしまいます。
オ OR GR1,=#F000
GR1に#246Cが設定されている状態で本命令を実行すると、GR1は#F46Cとなります。
カ OR GR1,=#FFFF
GR1に#246Cが設定されている状態で本命令を実行すると、GR1は#FFFFとなり、破壊されてしまいます。

設問1-b

穴埋め部分

15          ADDL GR1,GR2  
16          CPL  GR1,=10  ;10以上の場合は桁上げ
17          [  b  ]       

解答群

ア JMI MERGE
イ JNZ MERGE
ウ JPL MERGE
エ JOV MERGE
オ JZE MERGE

正解

ア JMI MERGE

解答方法

前ステップのコメント「10以上の場合は桁上げ」に着目します。
解答群の中で、GP1<10GP1≧10で処理を分岐できる命令は「ア JMI MERGE」だけですので、「ア」が正解となります。

解答群の解説

ア JMI MERGE
MERGEに分岐する条件は、GR1<10の時です。GR1≧10の時は分岐しません。
イ JNZ MERGE
MERGEに分岐する条件は、GR1≠10の時です。GR1=10の時は分岐しません。
ウ JPL MERGE
MERGEに分岐する条件は、GR1>10の時です。GR1≦10の時は分岐しません。
エ JOV MERGE
CPL命令では、フラグレジスタのOFフラグは設定されません。無意味な命令です。
オ JZE MERGE
MERGEに分岐する条件は、GR1=10の時です。GR1≠10の時は分岐しません。

設問1-c

穴埋め部分

20          [  c  ]          
21          OR   GR1,RESULT  ;中間結果との併合

解答群

ア SLA GR1,0,GR3
イ SLL GR1,0,GR3
ウ SLL GR1,=4
エ SRA GR1,0,GR3
オ SRL GR1,0,GR3
カ SRL GR1,=4

正解

イ SLL GR1,0,GR3

解答方法

LD   GR1,A  
SRL  GR1,0,GR3  
LD   GR2,B  
SRL  GR2,0,GR3  
AND  GR1,=#000F  
AND  GR2,=#000F  
ADDL GR1,GR2  
[  c  ]  
OR   GR1,RESULT  
パック10進数をメモリAから取り出し、その値を右方向に論理シフト(シフト量:GR3)し、最後に再びRESULTに格納しています。
右方向にシフトした場合、計算結果が失われてしまうため、「エ」「オ」「カ」は除外されます。
SRL GR2,0,GR3で右シフトした値を左シフトする命令を選択するのだが、「イ SLL GR1,0,GR3」が最もSRL GR2,0,GR3に近い。
ソーストレース後の解答方法
本か所では、以下のように処理が行われています。
メモリA/Bに退避されたパック10進数を取り出し、計算対象桁を最下位の4ビットに設定します。
再下位4ビットに設定された値を加算して、再びパック10進数の形式に戻(左シフト)します。
最後に、RESULTに格納されたパック10進数とマージします。

解答群の解説

ア SLA GR1,0,GR3
GR3の初期値は4(LAD GR3,4)で、4づつ加算(LAD GR3,4,GR3)されています。
CPL GR3,16で処理終了するので、GR3には、4,8または12が設定されます。
算術シフトの場合、“80”を左に12ビットシフトできません。
イ SLL GR1,0,GR3
左方向のシフト(シフト量:GR3)
ウ SLL GR1,=4
左方向のシフト(シフト量:4)
エ SRA GR1,0,GR3
右方向の算術シフト(シフト量:GR3)
AND  GR1,=#000F  
AND  GR2,=#000F  
ADDL GR1,GR2  
で下位4ビットに設定された加算結果を右シフトすると、加算結果が失われてしまいます。
オ SRL GR1,0,GR3
右方向の論理シフト(シフト量:GR3)
AND  GR1,=#000F  
AND  GR2,=#000F  
ADDL GR1,GR2  
で下位4ビットに設定された加算結果を右シフトすると、加算結果が失われてしまいます。
カ SRL GR1,=4
右方向の論理シフト(シフト量:4)
AND  GR1,=#000F  
AND  GR2,=#000F  
ADDL GR1,GR2  
で下位4ビットに設定された加算結果を右シフトすると、加算結果が失われてしまいます。

設問2-d

穴埋め部分

03          CPL  GR1,GR2  
04          [  d  ]       
05          LD   GR4,GR1  
06          LD   GR1,GR2  
07          LD   GR2,GR4  

解答群

ア JMI INI
イ JNZ INI
ウ JOV INI
エ JPL INI
オ JZE INI

正解

エ JPL INI

解答方法

穴埋個所の次の3ステップでは、G1とG2を入れ替えています。
このことを踏まえて、解答群の各命令を検証すると、「ア」と「エ」に絞り込まれます。
ST GR1,RESULT ;符号部を退避にて、GR1の符号が有効となっているので、GR1<GR2の時にG1とG2を入れ替える「エ」が正解となります。

解答群の解説

ア JMI INI
GR1<GR2の時に分岐し、GR1≧GR2の時にG1とG2を入れ替えます。
イ JNZ INI
GR1≠GR2の時に分岐し、GR1=GR2の時にG1とG2を入れ替えます。
G1とG2の入れ替え処理は、無駄な処理となってしましまいます。
ウ JOV INI
CPL命令では、フラグレジスタのOFフラグは設定されません。無意味な命令です。
エ JPL INI
GR1>GR2の時に分岐し、GR1≦GR2の時にG1とG2を入れ替えます。
オ JZE INI
GR1=GR2の時に分岐し、GR1≠GR2の時にG1とG2を入れ替えます。
GR1とGR2の入れ替えを行っても、GR1とGR2の関係はGR1≠GR2のままで変化しません。

設問2-e

穴埋め部分

20          SUBL GR1,GR2  
21          JPL  MERGE2   
22          [  e  ]       
23          ADDL GR1,=10  

解答群

ア JMI MERGE
イ JNZ MERGE
ウ JOV MERGE
エ JZE MERGE
オ SLL GR1,0,GR3
カ SRL GR1,0,GR3

正解

エ JZE MERGE

解答方法

本穴埋め個所は、プログラム1の[ b ]の穴埋め個所に相当しています。
プログラム1のコメント(10以上の場合は桁上げ)から、本穴埋め個所は、
「0未満の場合は桁下げ」
の処理を行うものと推測されます。
解答群の中で、0以上と0未満で処理を分岐できる命令は「エ JZE MERGE」だけですので、「エ」が正解となります。
「ア」「イ」「ウ」は、動作結果が同じになるので、除外されます。

解答群の解説

ア JMI MERGE
SUBL GR1,GR2  
JPL  MERGE  
JMI  MERGE  
の場合、減算結果が0の時だけ、
ADDL GR1,=10
が実行される。
イ JNZ MERGE
SUBL GR1,GR2  
JPL  MERGE  
JNZ  MERGE  
の場合、減算結果が0の時だけ、
ADDL GR1,=10
が実行される。
「ア」と同じ結果が得られる。
JPL MERGEは無駄な処理となる。
ウ JOV MERGE
SUBL GR1,GR2  
JPL  MERGE  
JOV MERGE  
の場合、減算結果が0の時だけ、
ADDL GR1,=10
が実行される。
「ア」と同じ結果が得られる。
(SUBLは論理減算なので、0未満になった時にフラグレジスタのOFフラグが設定される)
エ JZE MERGE
SUBL GR1,GR2  
JPL  MERGE  
JZE MERGE  
の場合、減算結果が負の時だけ、
ADDL GR1,=10
が実行される。
オ SLL GR1,0,GR3
SUBL GR1,GR2  
JPL  MERGE  
SLL GR1,0,GR3  
の場合、減算結果が0または負の時に、
SLL GR1,0,GR3
ADDL GR1,=10
が実行される。
カ SRL GR1,0,GR3
SUBL GR1,GR2  
JPL  MERGE  
SRL GR1,0,GR3  
の場合、減算結果が0または負の時に、
SRL GR1,0,GR3
ADDL GR1,=10
が実行される。

設問2-f

穴埋め部分

20          SUBL GR1,GR2    
34          SRL  GR2,0,GR3  
35          [  f  ]         
36          JUMP LOOP2      

解答群

ア ADDA GR1,GR0
イ ADDL GR1,=1
ウ ADDL GR1,GR0
エ ADDL GR3,GR0
オ SUBL GR1,=1
カ SUBL GR1,GR0

正解

カ SUBL GR1,GR0

解答方法

プログラム2は、プログラム1を流用改造しています。
プログラム1とプログラム2とで、本穴埋め個所周辺を比較します。
プログラム1
ADDL GR1,GR2  
(略)  
ADDL GR1,GR0  
JUMP LOOP  
プログラム2
SUBL GR1,GR2  
(略)  
[  f  ]  
JUMP LOOP  
プログラム1のADDL GR1,GR0に相当する命令が穴埋め個所に入ると推定されます。
このことを踏まえて、解答群の各命令を検証すると、「ア ADDA GR1,GR0」または「カ SUBL GR1,GR0」の可能性が高いと推定されます。
ソーストレース後の解答方法
本か所は、下位桁の計算で発生した桁下がり量を反映する個所です。
桁下がり量は、GR0に設定(0または1)されています。
桁下がり量を反映するには、減算操作が必要です。
よって、正解は、「カ SUBL GR1,GR0」となります。
注意
減算対象のGR1に0が設定されていて、1減算したことで桁下がりが発生することに対する考慮がなされていません。

解答群の解説

ア ADDA GR1,GR0
桁下がり量を加算しています。
イ ADDL GR1,=1
無条件に1加算しています。
ウ ADDL GR1,GR0
桁下がり量を加算しています。
エ ADDL GR3,GR0
GR3には、桁をシフトするシフト量が設定されています。
オ SUBL GR1,=1
無条件に1減算しています。
カ SUBL GR1,GR0
桁下がり量を減算しています。

設問3-g

穴埋め部分

02          LD   GR0,GR1  
03          [  g  ]       
04          SRL  GR0,1    

解答群

ア ADDL GR1,=1
イ AND  GR0,GR2
ウ OR   GR1,GR2
エ SUBL GR1,=1
オ XOR  GR0,GR2

正解

オ XOR GR0,GR2

解答方法

パック10進数の符号差異は、最下位ビットの差異で確認できます。
「ア」~「エ」では、符号差を認識することはできません。

解答群の解説

ア ADDL GR1,=1
符号部に1を加算しています。符号が’D’の時に1を加算すると、符号部には未定義の値が格納されてしまいます。
イ AND GR0,GR2
GR1とGR2の最下位ビットがともにOFFの時、GR0の最下位ビットはOFFになります。
GR1とGR2の最下位ビットの一方がONで他方がOFFの時、GR0の最下位ビットはOFFになります。
結果が同じなので、符号差を認識できません。
ウ OR GR1,GR2
GR1とGR2の最下位ビットがともにONの時、GR0の最下位ビットはONになります。
GR1とGR2の最下位ビットの一方がONで他方がOFFの時、GR0の最下位ビットはONになります。
結果が同じなので、符号差を認識できません。
エ SUBL GR1,=1
符号部から1を加算しています。符号が’C’の時に1を減算すると、符号部には未定義の値が格納されてしまいます。
オ XOR GR0,GR2
GR1とGR2の最下位ビットが同じ時、GR0の最下位ビットはOFFになります。
GR1とGR2の最下位ビットの一方がONで他方がOFFの時、GR0の最下位ビットはONになります。
結果が異なるので、符号差を認識できます。

設問3-h

穴埋め部分

02          LD   GR0,GR1  
03          XOR  GR0,GR2  
04          SRL  GR0,1    
05          [  h  ]       
06          CALL ADDP1    

解答群

ア JMI P2
イ JNZ P2
ウ JOV P2
エ JPL P2
オ JZE P2

正解

ウ JOV P2

解答方法

「ウ」を除く命令では、常に分岐するか、常に分岐しないので、無意味な命令です。

解答群の解説

ア JMI P2
右に論理シフトなので、最上位ビットは0となり、常に分岐しません。
イ JNZ P2
符号部は“C”または“D”なので、右に1ビットシフトした結果は、常に0ではありません。
常に分岐してしまいます。
ウ JOV P2
符号差がある場合、XOR GR0,GR2最下位ビットに1が設定されます。SRL GR0,1を実行することで最下位ビットがフラグレジスタのOFに反映されます。
エ JPL P2
右に論理シフトなので、最上位ビットは0となり、常に分岐します。
オ JZE P2
符号部は“C”または“D”なので、右に1ビットシフトした結果は、常に0ではありません。
常に分岐しません。

令和元年度 秋期 基本情報技術者試験(午後)問12 ソフトウェア開発(アセンブラ)の解き方

1 問題の解き方

午後問題は11問出題され、その中から5問を解答します。
分野 配点
1 情報セキュリティ 必須 20点
2~5 午前試験問題の応用 2問選択 各15点
6 アルゴリズム 必須 25点
7~11 各種言語 1問選択 25点
note
合格基準は60点
問1~5は午前向け試験対策で得点できます。ここで少なくとも7~8割(35~40点)得点し、問6~11の各問題で5~6割(25~30点)得点することを目指します。
アセンブラ問題の場合、プログラム全体を理解することなく、穴埋め部分周辺だけの解析で解ける問題があります。はじめにこれらの問題を解答し、次に、解析範囲を広げて解いていきます。
令和元年秋期問題の場合、穴埋め部分周辺だけの解析で、5割(8問中4問)を正解できます。
  • 正解できる問題:1-a、1-b、3-g、3-h
  • 絞り込みできる問題:2-d、2-e
  • 幅広い解析を要する問題:1-c、2-f
穴埋め部分周辺だけの解析方法
  1. コメントに着目し、解答群から正解を絞り込む。
  2. 前後の命令に着目し、解答群から正解を絞り込む。
  3. 解答群の命令に着目し、解答群から正解を絞り込む。

2 問題を解く1

穴埋め箇所周辺だけの解析で解答できる問題があります。 まず、穴埋め箇所周辺だけを解析して解答します。

2.1 設問1

1 - a

穴埋め個所
6         [  a  ]
7         ST   GR1,RESULT ;符号部を退避
解答群
ア AND GR1,=#000F
イ AND GR1,=#F000
ウ AND GR1,=#FFFF
エ OR  GR1,=#000F
オ OR  GR1,=#F000
カ OR  GR1,=#FFFF
解答手順
コメントに着目
  1. 「符号部を退避」のコメントに着目します。
  2. 解答群の中から、「符号部」に対して操作する命令を選びます。
    ⇒「ア」と「エ」が該当します。
  3. 「ア」と「エ」の「符号部」に対する操作内容を検証します。
    ⇒「エ」は「符号部」を破壊("F"で上書き)してるので除外されます。
  4. 「ア」の操作内容を確認します。
    ⇒「ア」は「符号部」以外を0クリアし、「符号部」を抽出しています。
  5. 正解は「ア」となります。
解答群解説
各選択肢の命令は、GR1を以下のように操作しています。
「数値部(上位12ビット)」を0クリアし、「符号部」を抽出します。
「符号部」に固定値("#0")を設定し、「符号部」を破壊します。
GR1の内容は変化しません。無駄な操作です。
「符号部」に固定値("#F")を設定し、「符号部」を破壊します。
100桁の位置に固定値("#F")を設定します。無意味な操作です。
「符号部」に固定値("#F")を設定し、「符号部」を破壊します。

1 - b

穴埋め個所
15         ADDL GR1,GR2
16         CPL  GR1,=10    ;10以上の場合は桁上げ
17         [  b  ]
18         SUBL GR1,=10
20  MERGE
解答群
ア JMI MERGE
イ JNZ MERGE
ウ JPL MERGE
エ JOV MERGE
オ JZE MERGE
解答手順
コメントに着目
  1. 「10以上の場合は桁上げ」のコメントに着目します。
  2. 解答群から"10以上""10未満"で処理を分岐できる命令を捜します。
    ⇒「ア」が該当します。
  3. 「ア」の操作内容を確認します。
    ⇒「ア」は"10未満"で分岐し、"10以上"で分岐しません。
  4. 正解は「ア」となります。
解答群解説
各選択肢の命令は、以下の条件で分岐します。
"(GR1 - 10) < 0"で分岐します。
すなわち、"GR1 < 10"で分岐します。"GR1 >= 10"で分岐せず。
"(GR1 - 10) ≠ 0"で分岐します。
すなわち、"GR1 ≠ 10"で分岐します。
"(GR1 - 10) > 0"で分岐します。
すなわち、"GR1 > 10"で分岐します。
比較命令ではフラグレジスタのOFは設定されません。
すなわち、常に、分岐しません。
"(GR1 - 10) = 0"で分岐します。
すなわち、"GR1 = 10"で分岐します。
point
"CPL"命令は内部で"GR1 - 10"の演算を行いその結果をフラグレジスタに反映します。 ("OF"には常に"0"が設定されます。JOVで分岐しません。)

1 - c

穴埋め個所
19         LAD  GR0,1
20  MERGE  [  c  ]
21         OR   GR1,RESULT ;中間結果との併合
解答群
ア SLA GR1,0,GR3
イ SLL GR1,0,GR3
ウ SLL GR1,=4
エ SRA GR1,0,GR3
オ SRL GR1,0,GR3
カ SRL GR1,=4
解答手順
コメントに着目
  1. 「中間結果との併合」のコメントに着目します。
    ⇒ヒントなし
前後の命令に着目
  1. 前後の数ステップを解析します。
    ⇒ヒントなし
解答群の命令に着目
  1. 解答群を確認します。
    ⇒シフト方法を解いていることが解りますが、絞り込むためのヒントなし
解答群解説
各選択肢の命令は、GR1を以下のように操作しています。
左方向に算術シフト。シフト量はGR3です。
左方向に論理シフト。シフト量はGR3です。
左方向に論理シフト。シフト量は4です。
右方向に算術シフト。シフト量はGR3です。
右方向に論理シフト。シフト量はGR3です。
右方向に論理シフト。シフト量は4です。

2.2 設問2

2 - d

穴埋め個所
3         CPL  GR1,GR2
4         [  d  ]
5         LD   GR4,GR1
6         LD   GR1,GR2
7         LD   GR2,GR4
8  INI    
解答群
ア JMI INI
イ JNZ INI
ウ JOV INI
エ JPL INI
オ JZE INI
解答手順
前後の命令に着目 {-}
  1. 解答群の命令は、いずれもINIへの分岐命令ですので、分岐しない時の処理内容(行番号4~7)を確認します。
    ⇒行番号4~7ではGR1とGR2の入れ替え行っています。
解答群の命令に着目 {-}
  1. 解答群から各命令を適用した場合の動作を確認します。(解答群解説参照)
    ⇒「ア」と「エ」に絞り込まれます。
  2. さらなる絞り込みは難しいので、次問に着手します。
解答群解説
各選択肢の命令実行で分岐しなかった時の処理を検証します。
"GR1 < GR2"の時に"INI"に分岐
"GR1 >= GR2"の時に分岐せず、GR1とGR2の入れ替えが実行され、"GR1 <= GR2"となります。
"GR1 ≠ GR2"の時に"INI"に分岐
"GR1 = GR2"の時に分岐せず、GR1とGR2の入れ替えが実行されます。 入れ替えを行っても"GR1 = GR2"の状態は変化しないので、本命令は無駄な処理となります。
比較命令では、OFには常に0が設定されます。
常に分岐しないので、本分岐命令は無駄な処理となります。
"GR1 > GR2"の時に"INI"に分岐
"GR1 <= GR2"の時に分岐せず、GR1とGR2の入れ替えが実行され、"GR1 >= GR2"となります。
"GR1 = GR2"の時に"INI"に分岐
"GR1 ≠ GR2"の時に分岐せず、GR1とGR2の入れ替えが実行されます。 入れ替えを行っても"GR1 ≠ GR2"の状態は変化しないので、本命令は無駄な処理となります。

2 - e

穴埋め個所
20         SUBL GR1,GR2
21         JPL  MERGE
22         [  e  ]
23         ADDL GR1,=1O
24         LAD  GRO,1
25  MERGE
解答群
ア JMI MERGE
イ JNZ MERGE
ウ JOV MERGE
エ JZE MERGE
オ SLL GR1,0,GR3
カ SRL GR1,0,GR3
解答手順
解答群の命令に着目
  1. 解答群から各命令を適用した場合の動作を確認します。(解答群解説参照)
    ⇒「ア」~「ウ」は同じ動作結果("GR1 = GR2"の時分岐せず)となるので除外されます。
  2. さらなる絞り込みは難しいので、次問に着手します。
解答群解説
各選択肢の命令を実施すると、以下のように処理されます。 1ステップ前の"JPL MERGE"と合わせて確認します。
"GR1 - GR2"の結果が正および負の時に分岐。 "GR1 = GR2"の時分岐せず。
"GR1 - GR2"の結果が正および0以外の時に分岐。 "GR1 = GR2"の時分岐せず。
"GR1 - GR2"の結果が正および負(0~65535範囲外)の時に分岐。 "GR1 = GR2"の時分岐せず。
"GR1 - GR2"の結果が正および0の時に分岐。"GR1 < GR2"の時分岐せず。
"GR1 - GR2"の結果が正の時に、左シフトし10加算。
"GR1 - GR2"の結果が正の時に、右シフトし10加算。

2 - f

穴埋め個所
31         LD   GR1,A
32         SRL  GR1,0,GR3
33         LD   GR2,B
34         SRL  GR2,0,GR3
35         [  f  ]
解答群
ア ADDA GR1,GR0
イ ADDL GR1,=1
ウ ADDL GR1,GR0
エ ADDL GR3,GR0
オ SUBL GR1,=1
カ SUBL GR1,GR0
解答手順
解答群の命令に着目
  1. 解答群から各命令を適用した場合の動作を確認します。(解答群解説参照)
    ⇒解答群からの絞り込みは難しいようです。
  2. さらなる絞り込みは難しいので、次問に着手します。
解答群解説
各選択肢の命令は、GR1を以下のように操作しています。
GR1 ← GR1 + GR0
GR1 ← GR1 + 1
GR1 ← GR1 + GR0
GR3 ← GR3 + GR0
GR1 ← GR1 - 1
GR1 ← GR1 - GR0

2.3 設問3

3 - g

穴埋め個所
2         LD   GR0,GR1
3         [  g  ]
4         SRL  GR0,1
5         [  h  ]
6         CALL ADDP1
7         JUMP FIN
8  P2     CALL ADDP2
解答群
ア ADDL GR1,=1
イ AND  GR0,GR2
ウ OR   GR1,GR2
エ SUBL GR1,=1
オ XOR  GR0,GR2
解答手順
前後の命令に着目
  1. 前後の命令では、GR2を参照していません。GR1とGR2の符号を比較するのであれば、GR2を参照する必要があります。
    ⇒GR2を参照する「イ」「ウ」「オ」に限定されます。
  2. 1ステップ後でGR0を操作しています。
    ⇒GR0を操作している「イ」と「オ」の可能性が高いようです。
  3. 「イ」と「オ」の実施結果を確認します。
    「イ」の場合の実施結果
    • 正+正の場合:"???C and ???C ⇒ ???C"
    • 正+負の場合:"???C and ???D ⇒ ???C"
    • 負+負の場合:"???D and ???D ⇒ ???D"
    「オ」の場合の実施結果
    • 正+正の場合:"???C xor ???C ⇒ ???0"
    • 正+負の場合:"???C xor ???D ⇒ ???1"
    • 負+負の場合:"???D xor ???D ⇒ ???0"
    「オ」の操作を実施することで、最下位ビットを参照することで判断(符号の差異)できることが解ります。
  4. 正解は「オ」となります。
解答群解説
各選択肢の命令を実施すると、以下のように処理されます。
入力された値の一方の「符号部」に1、加算されます。
数値部は変化しません。 符号部は、以下のように変化します。
"C+1 → D""D+1 → E"
入力された二つの値をANDします。
数値部の結果は不定です。 符号部は、以下のように変化します。
"C and C → C""C and D → C""D and D → D"
入力された二つの値をORします。
数値部の結果は不定です。 符号部は、以下のように変化します。
"C or C → C""C or D → D""D or D → D"
入力された値の一方の「符号部」から1、減算します。
数値部は変化しません。 符号部は、以下のように変化します。
"C-1 → B""D-1 → C"
入力された二つの値をXORします。
数値部の結果は不定です。 符号部は、以下のように変化します。
"C xor C → 0""C xor D → 1""D xor D → 0"
同じ符号なら0になり、異なる符号なら1になります。

3 - h

穴埋め個所
2         LD   GR0,GR1
3        [XOR  GR0,GR2]
4         SRL  GR0,1
5         [  h  ]
6         CALL ADDP1
7         JUMP FIN
8  P2     CALL ADDP2
解答群
ア JMI P2
イ JNZ P2
ウ JOV P2
エ JPL P2
オ JZE P2
解答手順
前後の命令に着目
  1. "XOR GR0,GR2"によって、符号が同じなら、最下位ビットが"0"となります。 符号が異なれば、最下位ビットが"1"となります。
    "SRL GR0,1"によって、最下位ビットがフラグレジスタの"OF"に反映されます。 「ウ」は、フラグレジスタの"OF"の状態によって、分岐を制御できます。
  2. 正解は「ウ」となります。
解答群の命令に着目
  1. 解答群から各命令を適用した場合の動作を確認します。(解答群解説参照)
    ⇒「ウ」以外、不適切な命令です。
  2. 正解は「ウ」となります。
解答群解説
行番号4は右方向の論理シフトなので、結果がマイナスになることはなく、常に分岐せず不適当です。
数値部は不定です。この分岐命令は数値部の影響も受けてしまうため不適当です。
(数値部が0でない時、常に分岐します。)
シフト命令によって、最下位ビットがフラグレジスタのOFに反映されます。
フラグレジスタのOFがONの時に分岐します。
数値部は不定です。この分岐命令は数値部の影響も受けてしまうため不適当です。
数値部が0でない時、常に分岐します。
数値部は不定です。この分岐命令は数値部の影響も受けてしまうため不適当です。
数値部が0でない時、常に分岐しません。

3 問題を解く2

3.1 設問1

1 - c

解答群
ア SLA GR1,0,GR3
イ SLL GR1,0,GR3
ウ SLL GR1,=4
エ SRA GR1,0,GR3
オ SRL GR1,0,GR3
カ SRL GR1,=4

解答群絞り込み

  1. [ c ]の次に“GR1 ← GR1 or RESULT”の処理が行われています。 GR1の最下位4ビットには加算結果が格納されています。 RESULTの最下位4ビットには符号が格納されています。 ⇒ “GR1 ← GR1 or RESULT”を実行すると加算結果が消失してしまいます。
  2. “GR1 ← GR1 or RESULT”前に右方向のシフトを行っても加算結果が消失してしまいます。 ⇒ 「エ」~「カ」は除外されます。
note
行番号11や行番号27に"SRL GR1,0,GR3"の処理があるので、同じ論理シフトでシフト量がGR3である「イ」を選択しても良いかもしれません。
  1. ループごとに"LAD GR3,4,GR3"でシフト量を+4することで、計算桁を、一桁→十桁→百桁と変えていきます。
  2. "OR GR1,RESULT"で中間結果と併合するにあたっては、GR1を左シフトします。 左シフト量が4固定では、一桁と十桁と百桁の計算結果が同じ場所に書き込まれてしまいます。 ⇒「ウ」が除外されます。
  3. 百桁の加算行った場合、12ビットのシフトが行われ、最上位4ビットにデータが格納されます。
    ⇒「ア」の算術シフトでは汎用レジスタの最上位ビットは変化しませんので、8より大きな数を表現できません。 ⇒「ア」が除外されます。
  4. 「イ」に絞り込まれます。

本プログラムの概要

本プログラムの概要は以下のとおりです。(本プログラムの詳細は、XXを参照してください。)
  1. 二つの入力値を退避
  2. シフト量(GR3) ← 4
  3. 計算結果域にGR1の符号格納(RESULT ← GR1 and #000F)
  4. 退避域から入力値を取出す
  5. 入力値を右シフト(シフト量はGR3)
  6. 下位4ビットを取り出す(GR1 ← GR1 and #000F)
  7. 桁上がり(GR0) ← 0
  8. 加算実施
  9. 結果が10以上なら、10減算(上位桁に10繰り上げ)し、桁上がり(GR0) ← 1
  10. [ c ]
  11. GR1に以前の計算結果を反映(GR1 ← GR1 or RESULT)
  12. シフト量(GR3) ← GR3 + 4
  13. 100桁の計算完了?計算完了なら復帰値作成へ
  14. 計算結果域に「計算結果+符号(GR1)」を格納
  15. 退避域から入力値を取出す
  16. 入力値を右シフト(シフト量はGR3) 計算対象桁を下位4ビットに設定
  17. 桁上がり反映(GR1 ← GR1 + GR0)
  18. 6.へ
  19. 復帰値作成
  20. 復帰

3.2 設問2

2 - d

解答群
ア JMI INI
エ JPL INI
note
既に「ア」と「エ」に絞り込まれています。

解答群絞り込み

  1. "GR1 - GR2"の計算を行っていること。」から、GR1の方が大きくなるように入れ替えを行っているものと推測されます。この推測が正しければ、正解は「エ」になります。
推定される減算方法は、以下の計算を行います。
  • 絶対値で大きい方から小さい方を減算する。
  • 絶対値の大きい方の符号が計算の符号とする。
トレースを実施すると、以下のことが解ります。
  • 百桁の減算を行った際に桁下がり処理が行われていない。
  • GR1から抽出した符号を計算結果の符号としている。 このことから、推定された減算方法で計算されていることが解ります。

本プログラムの概要

本プログラムの概要は以下のとおりです。(本プログラムの詳細は、XXを参照してください。)
  1. 二つの入力値の大小関係を比較
  2. [ d ]の時、二つの入力値を入れ替える
  3. 二つの入力値を退避
  4. シフト量(GR3) ← 4
  5. 計算結果域にGR1の符号格納(RESULT ← GR1 and #000F)
  6. 退避域から入力値を取出す
  7. 入力値を右シフト(シフト量はGR3)
  8. 下位4ビットを取り出す(GR1 ← GR1 and #000F)
  9. 桁下がり(GR0) ← 0
  10. 減算実施
  11. [ e ]の時、桁下がり処理スキップ
  12. 結果が負なら、10加算(上位桁から10を取り出す)し、桁下がり(GR0) ← 1
  13. 右シフトした値を元の位置にもどす(左シフト)(シフト量はGR3)
  14. GR1に以前の計算結果を反映(GR1 ← GR1 or RESULT)
  15. シフト量(GR3) ← GR3 + 4
  16. 100桁の計算完了?計算完了なら復帰値作成へ
  17. 計算結果域に「計算結果+符号(GR1)」を格納
  18. 退避域から入力値を取出す
  19. 入力値を右シフト(シフト量はGR3) 計算対象桁を下位4ビットに設定
  20. [ f ]
  21. 8.へ
  22. 復帰値作成(計算結果が“-0”なら“+0”に変更する)
  23. 復帰

2 - e

解答群
エ JZE MERGE
オ SLL GR1,0,GR3
カ SRL GR1,0,GR3
note
既に「エ」~「カ」に絞り込まれています。

解答群絞り込み

  1. プログラム1では当該箇所で加算処理を行っています。 この時、加算結果が10以上時に桁上げ処理を行っています。
  2. プログラム2の当該箇所で減算を行っています。 減算ではマイナス時に桁下げ処理が必要になります。 ⇒ 減算結果がプラスやゼロの時、桁下げが不要です。 ⇒ 「エ」の時、減算結果がゼロの時、桁下げ処理がスキップされます。

2 - f

解答群
ア ADDA GR1,GR0
イ ADDL GR1,=1
ウ ADDL GR1,GR0
エ ADDL GR3,GR0
オ SUBL GR1,=1
カ SUBL GR1,GR0

解答群絞り込み

  1. プログラム1では当該箇所で桁上げを行っています。
  2. プログラム2の当該箇所では桁下げ処理が必要になります。 ⇒ 減算結果がプラスやゼロの時、桁下げが不要です。 ⇒ 「カ」の時、桁下げ処理が実行されます。

プログラムの不具合

以下の場合、プログラムは正しく動作しません。(出題ミス) SUBL GR1,GR0実行時に、GR1が"0``の時、桁下がり処理が必要ですが実装されていません。 (例:“100 - 001”`を実行した場合、正しく計算されません。)
解答群解説
各選択肢の命令は、GR1を以下のように操作しています。
GR1 ← GR1 + GR0 (算術加算) 桁下げ発生時に、上位桁を+1します。正しい計算ではありません。
GR1 ← GR1 + 1 (論理加算) 桁下げ発生有無に関わらず無条件に、+1します。正しい計算ではありません。
GR1 ← GR1 + GR0 (論理加算) 桁下げ発生時に、+1します。正しい計算ではありません。
GR3 ← GR3 + GR0 (論理加算) シフト量を加算しています。
GR1 ← GR1 - 1 (論理減算) 桁下げ発生有無に関わらず無条件に、-1します。正しい計算ではありません。
GR1 ← GR1 - GR0 (論理減算) 桁下げ発生時に、-1します。正しい計算ではありません。

4 プログラム解説

4.1 設問1

プログラム1の説明

仕様は以下のとおりです。
  • 符号の同じ10進数加算プログラム。
  • 図1のように各桁は4ビットで表現。
  • 上位12ビットで3桁の数を表現(以降、数値部と呼ぶ)。
  • 下位4ビットは符号(以降、符号部と呼ぶ)。
  • 入力はGR1とGR2、出力はGR0。

プログラム1

 1  ADDP1  START
 2         RPUSH
 3         ST   GR1,A      ;GR1をAに退避
 4         ST   GR2,B      ;GR2をBに退避
 5         LAD  GR3,4      ;シフト数4設定(符号部シフト量)
 6        [AND  GR1,=#000F];符号部の抽出
 7         ST   GR1,RESULT ;符号部を退避
8         LD   GR1,A      ;GR1復元
9         SRL  GR1,0,GR3  ;1桁目を下位4ビットに設定
10         LD   GR2,B      ;GR2復元
11         SRL  GR2,0,GR3  ;1桁目を下位4ビットに設定
12  L00P   AND  GR1,=#000F ;計算対象桁以外をクリア
13         AND  GR2,=#000F ;計算対象桁以外をクリア
14         LAD  GR0,0      ;桁上がりフラグクリア
15         ADDL GR1,GR2    ;加算
16         CPL  GR1,=10    ;10以上の場合は桁上げ
17        [JMI  MERGE]     ;10未満時分岐
18         SUBL GR1,=10    ;10以上時10減算
19         LAD  GR0,1      ;桁上がりフラグセット
20  MERGE [SLL  GR1,0,GR3] ;計算対象桁を元の位置に復元
21         OR   GR1,RESULT ;中間結果との併合
22         LAD  GR3,4,GR3  ;シフト量更新
23         CPL  GR3,=16    ;100桁まで計算完了?
24         JZE  FIN        ;終了判定
25         ST   GR1,RESULT ;中間結果を退避
26         LD   GR1,A      ;GR1復元
27         SRL  GR1,0,GR3  ;計算対象桁を下位4ビットに設定
28         LD   GR2,B      ;GR2復元
29         SRL  GR2,0,GR3  ;計算対象桁を下位4ビットに設定
30         ADDL GR1,GR0    ;桁上がりフラグ反映
31         JUMP L00P
32  FIN    LD   GR0,GR1    ;計算結果を復帰値に設定
33         RP0P
34         RET
35  A      DS              ;G1退避域
36  B      DS              ;G2退避域
37  RESULT DS              ;計算結果退避域
38         END

4.2 設問2

プログラム2の説明

仕様は以下のとおりです。
  • 符号の異なる10進数加算プログラム。

プログラム2

 1  ADDP2  START
 2         RPUSH
3         CPL  GR1,GR2   ;二つの入力値の大小関係比較
4        [JPL  INI]      ;GR1 > GR2なら分岐
5         LD   GR4,GR1   ;G1,G2入れ替え
6         LD   GR1,GR2
7         LD   GR2,GR4
 8  INI    ST   GR1,A      ;GR1をAに退避
 9         ST   GR2,B      ;GR2をBに退避
10         LAD  GR3,4      ;シフト数4設定(符号部シフト量)
11        [AND  GR1,=#000F];符号部の抽出
12         ST   GR1,RESULT ;符号部を退避
13         LD   GR1,A      ;GR1復元
14         SRL  GR1,0,GR3  ;1桁目を下位4ビットに設定
15         LD   GR2,B      ;GR2復元
16         SRL  GR2,0,GR3  ;1桁目を下位4ビットに設定
17  L00P   AND  GR1,=#000F ;計算対象桁以外をクリア
18         AND  GR2,=#000F ;計算対象桁以外をクリア
19         LAD  GR0,0      ;桁下がりフラグクリア
20         SUBL GR1,GR2    ;減算
21         JPL  MERGE      ;正時、分岐
22        [JZE  MERGE]     ;0時、分岐
23         ADDL GR1,=10    ;桁下がり時10加算
24         LAD  GR0,1      ;桁下がりフラグセット
25  MERGE [SLL  GR1,0,GR3] ;計算対象桁を元の位置に復元
26         OR   GR1,RESULT ;中間結果との併合
27         LAD  GR3,4,GR3  ;シフト量更新
28         CPL  GR3,=16    ;100桁まで計算完了?
29         JZE  FIN        ;終了判定
30         ST   GR1,RESULT ;中間結果を退避
31         LD   GR1,A      ;GR1復元
32         SRL  GR1,0,GR3  ;計算対象桁を下位4ビットに設定
33         LD   GR2,B      ;GR2復元
34         SRL  GR2,0,GR3  ;計算対象桁を下位4ビットに設定
35        [SUBL GR1,GR0]   ;桁下がりフラグ反映
36         JUMP L00P
37  FIN    LD   GR0,GR1    ;計算結果を復帰値に設定
38         CPL  GR0,=#000D ;計算開始時に絶対値の大きい方に符号設定
39         JNZ  FIN2
40         LAD  GR0,=#000C
41  FIN2   RP0P
42         RET
43  A      DS
44  B      DS
45  RESULT DS
46         END

4.3 設問3

プログラム3の説明

仕様は以下のとおりです。
  • 符号の組み合わせでプログラム1とプログラム2を呼び分けるプログラム。
  • 符号が同じなら"ADD1"実行、符号が異なるなら"ADD2"実行。
point
「符号が同じかどうかは、最下位ビットが同じかどうかで判断できます。

プログラム3

 1  ADDP   START
2         LD   GR0,GR1
3        [XOR  GR0,GR2]  ;最下位ビット差異明確化
4         SRL  GR0,1     ;最下位ビット抽出
5        [JOV  P2]       ;最下位ビット一致不一致判定
6         CALL ADDP1     ;一致時
7         JUMP FIN
8  P2     CALL ADDP2     ;不一致時
9  FIN    RET
10         END

アセンブラ プログラムの解説 平成30年度 秋期

プログラムの概要

モジュール構成



プログラム概要





プログラムの詳細





プログラム1























プログラム2














設問の開設

設問1











アセンブラ プログラムの解説 平成31年度 春期

平成31年度 春期のプログラム解説です。
行番号14までの解説です。

データ構成




モジュール構成




BITSON 処理概要



BITSON 行番号3~9


BITSON 行番号10~14



基本情報技術者試験 アセンブラ(CASL) 原稿 20210529

  基本情報技術者試験 アセンブラ(CASL) 簡単に5割 平成21年春期,平成21年秋期 平成21春期 平成21秋期 平成22春期 平成22秋期 平成21春期 概要 解き方 設問1-a 設問1-b 設問1-c 設問2-d...