平成21春 問12 アセンブラ のプログラミング(コメント付き)

アセンブラ過去問プログラミング
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
息抜きに、写真で癒し(=^・^=)

基本情報技術者試験がコロナで中止や延期になり、中々プログラミングのスキルも身に付かずに悶々としていたので、思い切って過去問を頼りにプログラミングをして見ることにしました。第一回は平成21年春の問題です。

プログラムMULSは、被乗数(かけ「られる」数)32ビットと、乗数(かける数)16ビットの計算をして、その結果である積32ビットを返します。
被乗数と乗数のどっちがどっちか分からなくなりそうなので、被乗数のラベルをかけ「られる」数から、RARERU、乗数をKERU、積をSEKIと名付けてプログラミングしました。GR1にはRARERUの先頭アドレス、GR2にはRERUそのもの、GR3にはSEKIの先頭アドレスを設定しています。

具体例として、被乗数RARERUの上位語には16進数で「2」、下位語には16進数で「6」、乗数KERUには16進数「3」とします。
プログラミングの名前はH21SMULSとします。

プログラミングは下記になります。
シミュレーターと過去問を解くまでの勉強に使った参考書はこちらです

<<プログラミング>>
H21SMULS START
RPUSH
LAD GR1,RARERU ;かけ「られる」数の先頭アドレスをGR1
LD GR2,KERU ;かける数自体をGR2
LAD GR3,SEKI ;積の先頭アドレスをGR3
LAD GR6,0 ;積 上位語の初期化
LAD GR7,0 ;積 下位語の初期化
LD GR4,0,GR1 ;被乗数 上位語の取出し
LD GR5,1,GR1 ;被乗数 下位語の取出し
LP SRL GR2,1 ;乗数を1ビット右にシフト
JOV ADD32 ;「a」最下位桁がゼロかどうかで分岐する
JZE FIN ;全部乗数が0だったら押しマシ
JUMP NEXT ;加算処理をスキップ(下位桁が0だった場合)
ADD32 ADDL GR6,GR4 ;被乗数の上位語を足す
ADDL GR7,GR5 ;被乗数の下位語を足す
JOV ADJ1 ;「b」下位語の加算で桁上りした場合に分岐
JUMP NEXT ;下位語の桁上げが無いので桁上げ処理をスキップ
ADJ1 ADDL GR6,=1 ;桁上げ処理(下位桁オーバーフローで上位桁へ)
NEXT SLL GR4,1 ;被乗数の上位語を1ビット左にシフト
SLL GR5,1 ;「c」被乗数の下位語を1ビット左にシフト
JOV ADJ32 ;左シフトによって桁上りした下位語の分を上位語へ
JUMP LP ;次の計算処理へ
ADJ32 OR GR4,=1 ;上位語に下位語からの桁上りを足しこむ
JUMP LP ;次の計算処理へ
FIN ST GR6,0,GR3 ;乗算結果(上位語)の格納
ST GR7,1,GR3 ;乗算結果(下位語)の格納
RPOP
RET
RARERU DC #2
DC #6
KERU DC #3
SEKI DS 2
END

それでは動かして見ます。


GR1、GR2、GR3にそれぞれ被乗数先頭アドレス、乗数、積の先頭アドレスが入り、
GR4に被乗数の上位語、GR5に被乗数の下位語、GR6、GR7に積の値のゼロによる初期化が入りました。

ループ1回目
GR2が1ビット右シフトしました。また、OFが1なので、オーバーフローしました。

GR6、GR7に被乗数の上位語下位語が足されました。

GR4、GR5に被乗数が左に1ビットされて2倍になりました。

ループ2回目

GR2に乗数が右に1ビットされ、OF、ZFが1になりました。

GR6、GR7に被乗数の上位語下位語とシフトした分が足されました。

GR4、GR5に被乗数が左に1ビットされて2倍になりました。

ループ3回目
ゼロフラグが1になりました。

では次に、プログラム2のMULを作ります。
名前をH21SMULにします。

プログラムMULは、被乗数(かけ「られる」数)32ビットと、乗数(かける数)32ビットの計算をして、その結果である積32ビットを返します。
被乗数のラベルをかけ「られる」数から、RARERU2、
乗数をKERU2、積をSEKI2と名付けてプログラミングしました。
GR1にはRARERU2の先頭アドレス、GR2にはRERU2の先頭アドレス、GR3にはSEKI2の先頭アドレスを設定しています。
また、領域SVは、計算結果の退避につかいます。

具体例として、被乗数RARERU2の上位語には16進数で「2」、下位語には16進数で「6」、乗数KERU2には上位語「3」、下位語「5」とします。
プログラミングの名前はH21SMULとします。

プログラミングは下記になります。
先ほどのH21SMULSを副プログラムとして呼び出して使用します。
その際の渡す値は主プログラムから渡されるので、副プログラムの方は消しました。

<<プログラミング>>
H21SMUL START
RPUSH
LAD GR1,RARERU2 ;かけ「られる」数の先頭アドレスをGR1
LAD GR2,KERU2 ;かける数自体をGR2
LAD GR3,SEKI2 ;積の先頭アドレスをGR3
PUSH 0,GR3 ;積の上位語のアドレスをスタックに積む
PUSH 0,GR2 ;乗数の上位語のアドレスをスタックに積む
LD GR2,1,GR2 ;乗数の下位語を読み込む
CALL H21SMULS ;プログラム1を呼ぶ 被乗数×乗数下位語→積A
POP GR2 ;スタックから乗数の先頭アドレスを取り出す
LD GR2,0,GR2 ;「d」乗数の上位語を読み込む
LAD GR3,SV ;結果(積B)の格納先として作業領域SVの先頭アドレスを設定
CALL H21SMULS ;プログラム1を呼ぶ 被乗数×乗数上位語→積B
LD GR6,1,GR3 ;「e」積Bの下位語であるSV+1の値を読み込む
POP GR3 ;積Aの上位語のアドレスを取り出す
ADDL GR6,0,GR3 ;積Aの上位語と積Bの下位語を加算
ST GR6,0,GR3 ;加算結果をGR3に格納
RPOP
RET
SV DS 2 ;積Bの2語分(結果退避用)
RARERU2 DC #2 ;被乗数(かけられる数)上位語
DC #6 ;被乗数(かけられる数)下位語
KERU2 DC #3 ;乗数(かける数)上位語
DC #5 ;乗数(かける数)下位語
SEKI2 DS 2 ;積の2語分


H21SMULS
RPUSH
LAD GR6,0 ;積 上位語の初期化
LAD GR7,0 ;積 下位語の初期化
LD GR4,0,GR1 ;被乗数 上位語の取出し
LD GR5,1,GR1 ;被乗数 下位語の取出し
LP SRL GR2,1 ;乗数を1ビット右にシフト
JOV ADD32 ;「a」最下位桁がゼロかどうかで分岐する
JZE FIN ;全部乗数が0だったら押しマシ
JUMP NEXT ;加算処理をスキップ(下位桁が0だった場合)
ADD32 ADDL GR6,GR4 ;被乗数の上位語を足す
ADDL GR7,GR5 ;被乗数の下位語を足す
JOV ADJ1 ;「b」下位語の加算で桁上りした場合に分岐
JUMP NEXT ;下位語の桁上げが無いので桁上げ処理をスキップ
ADJ1 ADDL GR6,=1 ;桁上げ処理(下位桁オーバーフローで上位桁へ)
NEXT SLL GR4,1 ;被乗数の上位語を1ビット左にシフト
SLL GR5,1 ;「c」被乗数の下位語を1ビット左にシフト
JOV ADJ32 ;左シフトによって桁上りした下位語の分を上位語へ
JUMP LP ;次の計算処理へ
ADJ32 OR GR4,=1 ;上位語に下位語からの桁上りを足しこむ
JUMP LP ;次の計算処理へ
FIN ST GR6,0,GR3 ;乗算結果(上位語)の格納
ST GR7,1,GR3 ;乗算結果(下位語)の格納
RPOP
RET
END

それでは動かして見ます。
GR1、GR2、GR3にそれぞれ被乗数、乗数、積のアドレスが入りました。

スタックにGR3、GR2にそれぞれ設定したアドレスが積まれました。

GR2に乗数(かける数)の下位語である「5」が入りました。

副プログラムMULSを呼び出しました。

GR6、GR7が積の計算結果の初期化されました。

GR4、GR5に被乗数の上位語、下位語が入りました。

下位語積Aのループ1回目
GR2に乗数かける数が右シフトされました。

GR6、GR7に、計算結果が加算されました。

GR4、GR5で被乗数かけられる数の上位語、下位語が左シフトされました。

下位語積Aのループ2回目

GR2が右シフトされました。
下位桁が0なので、加算はスキップします。

GR4、GR5が左シフトされました。

下位語積Aのループ3回目
GR2で乗数が右シフトしました。
オーバーフローしたので、下位桁が1です。

GR6、GR7で、積の計算結果に加算されました。

GR4、GR5で被乗数(かけられる数)をシフトします。

呼び出し元に戻ります。
GR2に、乗数(かける数)の上位語(先頭)アドレスが入ります。

GR2に乗数の上位語が入ります。

GR3に計算結果退避領域の先頭アドレスが入ります。

副プログラムが呼び出されました。

以下、重複はなるべく避けてトレースします。

上位語積Bのループ1回目

乗数が右シフトされました。


計算結果が加算されました。

被乗数が左シフトされました。

上位語積Bのループ2回目
乗数が右シフトされました。

計算結果に足しこまれました。

被乗数が左シフトされました。

呼び出し元に戻りました。

GR6にGR3(積Bの計算結果)の下位語が入りました。

GR3にSEKI2の先頭アドレス(積Aの計算結果上位語を指す)が入りました。

GR6に演算結果が求められました。

では、トレースに使ったノートです。

シミュレーターと過去問を解くまでの勉強に使った参考書はこちらです

アセンブラ過去問プログラミング
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
息抜きに、写真で癒し(=^・^=)