この記事では、過去問のアセンブラの問題に載っているプログラムを実際に自分の環境で作成して動かすのに使ったコードと、トレースのノートを掲載しています。
この記事を通してアセンブラだけでなくアルゴリズムのトレース力向上にもお役立て下さい。
アセンブラ過去問プログラミング
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
令和2年度(令和3年1月合格報告)
シミュレーターと過去問を解くまでの勉強に使った参考書はこちらです
この回の過去問は少し難しいというか、ややこしいと思います。なので、この記事をご覧になる前に、
平成21年秋過去問問12アセンブラ
平成25年春過去問問12アセンブラ
をご覧下さい。
この記事を更新している今現在は設問全て理解出来ましたが、理解するまでに手間取ってしまいました。
この問題苦手かも知れません。この記事でトレースしたり明日も問題を解いてみたりして、もう少し練習したいです。
試験が心配になってきた・・・。
ではこの問題について見ていきます。
1語16ビットで2語、つまり31ビット分のαという領域があります。
こんな感じです。
α+0「0011011000000000」
α+1「0000000000000000」
このαの一部がβという領域のビットと一致するところがあり、その位置を求めます。
β「11011」
α+0の2ビット目(先頭は0ビット)から5ビット分がβと一致します。
プログラム1「BSRH」では一致した位置の「2」がGR0に設定して呼び出し元に戻ります。
βはGR2に左詰めで「1101100000000000」と設定されます。
n=5ビット分の5はGR3に5、GR1はα+0を設定します。
ここまでの流れをノートにまとめました。
プログラミングする時は16進数で指定します。
α+0を16進数すると「3600」、α+1は「0000」、βは「D800」になります。
尚、シミュレータのレジスタの値は、2進数で表示します。
では、シミュレーターを使ってのトレースをします。
GR1にα+0の「アドレス」が、GR2にβ、GR3にビット数の5が設定されました。
プログラム1のBSRHを呼びます。
GR0に-1が入りました。αとβの一致するビットが見つからなかった時にGR0で-1を返します。
初期値として見つからなかった時の値が入りました。
GR6にマスク生成されます。
対象ビット以外をマスクする様にします。
対象の5ビット分右シフトされました。
マスクが反転されました。
これで、論理積を取ると対象の5ビット分以外が0になります。
GR4にα+0が入りました。
GR5にα+1が入りました。
GR1に2語分のビットの32が入りました。
GR1に32-5で27が入りました。
GR3に27が写されました。この差で一致するビットの位置を求めます。
GR7にGR4のα+0が写されました。
GR6のマスクと論理積を取って、最初の5ビットが取り出されました。
次に、GR2TO
GR7でGR2との排他的論理和を取ります。
もしも最初の5ビットが一致していたら0になります。・・・空欄「a」
0にならなかったので、一致しませんでした。
GR1が27から1を引いて26になりました。
GR4のα+0が左に1ビットシフトされました。
GR5のα+1も左に1ビットシフトされました。(0なので値変わらず)・・・空欄「b」
ループに戻ります。
GR7にα+0を左に1ビットした値が入りました。
GR6のマスクとの論理積で、GR7の先頭の5ビットが取り出されました。
GR7でGR2との排他的論理和を取ります。
もしも最初の5ビットが一致していたら0になります。
0にならなかったので、一致しませんでした。
26から1を引いて、25になりました。
GR4で、α+0を1ビット左シフトした値が更に1ビット左シフトされました。
GR5のα+1も左に1ビットシフトされました。(0なので値変わらず)
ループに戻ります。
GR4で、α+0が2ビット左シフトされた値がGR7に入ります。
GR6のマスクとの論理シフトされて先頭5ビットが取り出されました。
GR7でGR2との排他的論理和を取ります。
もしも最初の5ビットが一致していたら0になります。
GR2との排他的論理和で0になったので一致していました。
ラベルFOUNDに分岐します。
27-25で処理したビット分の2が求められました。
ビット位置2がGR0に入りました。
プログラムが終了しました。
;平成29年秋一致するビットを求めてその分置換する
;主プログラム
MAIN START
RPUSH
LAD GR1,ALPHA ;アドレスα+0を設定
LD GR2,BETA ;βを読み込む
LD GR3,N ;ビット数を読み込む
CALL BSRH ;プログラム1へ
RPOP
RET
ALPHA DC #3600 ;α+0
DC #0000 ;α+1
BETA DC #D800 ;β
N DC 5 ;ビット数
;プログラム1
BSRH RPUSH
LD GR0,=-1 ;初期値設定
LD GR6,=#FFFF ;マスク作成
SRL GR6,0,GR3 ;Nビット分だけ右シフト
XOR GR6,=#FFFF ;マスクのビットを反転
LD GR4,0,GR1 ;α+0の取り出し
LD GR5,1,GR1 ;α+1の取り出し
LD GR1,=32
SUBA GR1,GR3 ;GR1←32-n
LD GR3,GR1 ;GR3←32-n
LPH LD GR7,GR4 ;α+0の退避
AND GR7,GR6 ;マスクで対象部分を抜き出す
XOR GR7,GR2 ;空欄「a」結果が0なら一致
JZE FOUND ;一致あり
SUBA GR1,=1 ;処理済み分デクリメント
JMI FIN ;一致無し
SLL GR4,1 ;α+0を1ビット左シフト
SLL GR5,1 ;α+1も。オーバーフローしたらα+0へ
JOV NEXT ;空欄「b」↑の処理へ分岐
JUMP LPH
NEXT OR GR4,=#0001 ;2語目のオーバーフローした分
JUMP LPH
FOUND SUBA GR3,GR1 ;pの算出
LD GR0,GR3
FIN RPOP
RET
END
設問1が全て解答出来ました。
4行目:「1111111111111111」
5行目:「0000011111111111」
6行目:「1111100000000000」
で、対象ビットを取り出すマスクが出来ました。
これと同じ処理は、
「1000000000000000」これを、
「1111100000000000」にするので、
「算術シフト」を使います。先頭のビットが1なので、同じビットが入る算術シフトを
作る方法でもマスクが作れます。
-1してあるのでは、先頭の1の分があるのでその分引くからです。
この具体例ではマスクの1は1が5つになるようにします。つまり、
右4ビット「算術」シフトします。
もしも伝わりにくかったら、平成25年春アセンブラに詳細を書きましたので、
そちらをご覧下さい(=^・^=)m
では、設問3と4に行きます。
設問3は設問4の具体例を使うと、空欄「d」と設問4が一度に解けるので、その具体例を使います。
α+0「1111111111110011」
α+1「0111111111111111」
β 「11011」
n 「5」
γ 「11110」
この例ですと、1語目の後ろから2ビット(14ビット)~2語目の2ビット目までの5ビット間を置換します。
なので、実行後は
α+0「1111111111110011」(こっちは変わらず)
α+1「1101111111111111」(先頭から3ビット分変わっています)
になります。
ここまでの流れをノートにまとめました。
では、シミュレーターを動かしながらトレースをします。
主記憶の領域にα、β、n、γの所に問題文の値が設定されました。
実行後はα+0は変わりませんが、α+1が「DFFF」になります。
プログラム1のトレースの所は省略します。
αとβが一致するところが14ビット目なので、GR0に
14が求まります。それがGR2に入りました。
GR6でマスク生成されます。
右に5ビットシフトしました。
反転してマスクが完成しました。
対象のビット5が入りました。
1語のみなのか、1語と2語にまたがるのか、2語のみなのか判定するのに使うので、
16が入りました。
16から14を引いて2と求まりました。
GR3の2とGR7の対象ビット5が比較されました。
GR3の方が小さいので1語と2語にまたがります。
GR4のγがGR5に退避されました。
GR6のマスクがGR7に退避されました。
GR4が14ビットシフトされました。
GR6が14ビットシフトされました。
GR2にαの1語目が入りました。
マスクのGR6が反転されました。
GR6との論理積を取りました。
γの一部が足されて、1語目の置換処理が終了しました。
退避していたγがGR4に戻りました。
退避していたマスクがGR6に戻りました。
γが2語目の2ビット分GR4左シフトされました。
マスクも2ビットシフトされました・・・設問4の解答です(=^・^=)m
α+1のアドレスが入りました。
2語目が読み込まれました。
マスクが反転されました。
GR6のマスクとの論理積を取りました。
γの一部が足しこまれて置換が完了しました。・・・空欄「d」
2語目のα+1が主記憶に格納されました。
終了しました。
プログラムとノートです。
プログラム1の画像は省略しています。
;平成29年秋一致するビットを求めてその分置換する
;主プログラム
MAIN START
RPUSH
LAD GR1,ALPHA ;アドレスα+0を設定
LD GR2,BETA ;βを読み込む
LD GR3,N ;ビット数を読み込む
LD GR4,GAMMA ;γを読み込む
CALL BREP ;プログラム2へ
RPOP
RET
ALPHA DC #FFF3 ;α+0
DC #7FFF ;α+1
BETA DC #D800 ;β
N DC 5 ;ビット数
GAMMA DC #F000 ;γ
;プログラム2
BREP
RPUSH
CALL BSRH ;プログラム1を呼ぶ
LD GR2,GR0 ;一致したビットの位置が入る
JMI FIN
LD GR6,=#FFFF ;マスク生成
SRL GR6,0,GR3
XOR GR6,=#FFFF
LD GR7,GR3 ;GR7←n
LD GR3,=16
SUBA GR3,GR2 ;GR3←16-n
JMI ONL2 ;一致する部分ビット列が2語目だけのとき
JZE ONL2
CPA GR3,GR7 ;(16-p)とnの比較
JMI NEXTP ;2語にまたがる処理
JUMP ONL1 ;一致するビットが1語目だけのとき
NEXTP LD GR5,GR4 ;γを退避
LD GR7,GR6 ;マスクを退避
CALL S1
LD GR4,GR5
LD GR6,GR7
SLL GR4,0,GR3 ;2語目用γの調整
SLL GR6,0,GR3 ;2語目用マスクの調整
LAD GR1,1,GR1
CALL S2 ;2語目の最終処理
JUMP FINP
ONL1 CALL S1
JUMP FINP
ONL2 LD GR2,=0 ;空欄「c」シフトするビット数
SUBA GR2,GR3 ;GR2←p-16
LAD GR1,1,GR1 ;操作対象を2語目にして、
CALL S1 ;2語目の処理
FINP RPOP
RET
S1 SRL GR4,0,GR2 ;γの調整
SRL GR6,0,GR2 ;マスクの調整
S2 LD GR2,0,GR1 ;操作対象後の取り出し
XOR GR6,=#FFFF
AND GR2,GR6
OR GR2,GR4 ;空欄「d」で置換処理
ST GR2,0,GR1
RET
;プログラム1
BSRH RPUSH
LD GR0,=-1 ;初期値設定
LD GR6,=#FFFF ;マスク作成
SRL GR6,0,GR3 ;Nビット分だけ右シフト
XOR GR6,=#FFFF ;マスクのビットを反転
LD GR4,0,GR1 ;α+0の取り出し
LD GR5,1,GR1 ;α+1の取り出し
LD GR1,=32
SUBA GR1,GR3 ;GR1←32-n
LD GR3,GR1 ;GR3←32-n
LPH LD GR7,GR4 ;α+0の退避
AND GR7,GR6 ;マスクで対象部分を抜き出す
XOR GR7,GR2 ;空欄「a」結果が0なら一致
JZE FOUND ;一致あり
SUBA GR1,=1 ;処理済み分デクリメント
JMI FIN ;一致無し
SLL GR4,1 ;α+0を1ビット左シフト
SLL GR5,1 ;α+1も。オーバーフローしたらα+0へ
JOV NEXT ;空欄「b」↑の処理へ分岐
JUMP LPH
NEXT OR GR4,=#0001 ;2語目のオーバーフローした分
JUMP LPH
FOUND SUBA GR3,GR1 ;pの算出
LD GR0,GR3
FIN RPOP
RET
END
空欄「c」を埋めるのに2語目のみ置換対象となる具体例を考えましたので、それで
トレースをします。
α+0「0000000000000000」
α+1「0110110000000000」
β 「11011」
n 「3」
γ 「11111」
主プログラムのここの所のみを変えました。
空欄cのある所とその少し後までトレースをします。
2語目の1ビットなので、17を返してレジスタに移された所から始めます。
GR2に17が入りました。
GR6にマスクが作成されました。
対象のビットが入りました。
1語目のみ、2語目のみ、1、2語にまたがるを判定するのに使う16が入りました。
16-17で-1になり、2語目のみと判定されました。
GR2がゼロクリアされました。・・・空欄「c」
これは後でマスクをシフトするビットを求めるのに使います。
0-(-1)で1が求まりましたので1ビットシフトするのに使います。
以下略
ここまでの流れをノートにまとめました。
お疲れ様でした。
今度受けるので、自分の勉強になりました。
どなたかのお役に立てたらうれしいです。
誰も見ていなかったら泣いちゃいます( ;∀;)
どなたか見ている人いますか?いたら手を振って下さい(=^・^=)
要領悪すぎにゃ~~~~~~( ;∀;)(=^・^=)( ;∀;) (^O^)/