この記事では、過去問のアセンブラの問題に載っているプログラムを実際に自分の環境で作成して動かすのに使ったコードと、トレースのノートを掲載しています。
この記事を通してアセンブラだけでなくアルゴリズムのトレース力向上にもお役立て下さい。
アセンブラ過去問プログラミング
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
令和2年度(令和3年1月合格報告)
シミュレーターと過去問を解くまでの勉強に使った参考書はこちらです
割り算プログラムの問題です。
具体例として、被除数(以下、割られる数)を50、除数(以下、割る数)を20とします。そうすると、商が2、余りが10になります。
入力
GR1:#0000(割られる数の上位語)
GR2:#0032(割られる数の下位語で50)
GR3:割る数が格納してある領域「WARU」の先頭アドレス「WARU+0」
GR3+1:WARU+1
割る数には20の16進数表記#0014を入れました。
このプログラム1を実行すると、
出力
GR1:#0000(商の上位語)
GR2:#0002(商の下位語で2)
GR4:#0000(余りの上位語)
GR5:#000A(余り語下位語で10)
となります。
では、ステップ実行していきます。
実行すると、割る数の上位語下位語が入りました。下位語は20の16進数表記、#0014が入りました。
次に、割られる数の上位語#0000、下位語50の#0032が入りました。
ここで、メインプログラムから割り算プログラムのDIVが呼び出されました。
割れれる数の上位語下位語がそれぞれ退避されました。
商の上位語下位語が初期化されました。
ループに入り、割られる数の上位語下位語が退避されました。
これは余りを求めるのに使います。
割り算実行前の商が上位語、下位語ともに入りました。
1回目の割り算処理が実行されました。
50から20を引いて30になり、その16進数の#001Eが入りました。
1回目の割り算処理実行後の結果が退避されました。
商がカウントアップされました。
30から20を引いた余りの10が求まりました。
2回目の割り算処理実行後の結果が退避されました。
商がカウントアップされました。
余りの10から割る数の20を引いたらオーバーフローしました。
プログラム1が終わりました。
プログラム1はこちらになります。
トレースに使ったノートはこちらになります。
;平成23年秋…割り算プログラム1
;呼び出し元のメインプログラム
MAIN START
RPUSH
LD GR1,=#0000 ;割られる数の上位語
LD GR2,=#0032 ;その下位語で50
LAD GR3,WARU ;結果領域先頭後
CALL DIV
RPOP
RET
WARU DC #0000 ;割る数上位語
DC #0014 ;割る数下位語で20
;プログラム1
DIV
PUSH 0,GR6
PUSH 0,GR7
LD GR6,GR1 ;割られる数の上位語
LD GR7,GR2 ;割られる数の下位語
LD GR1,=#FFFF ;商の初期化
LD GR2,=#FFFF
LP LD GR4,GR6 ;割られる数の上位語
LD GR5,GR7 ;割られる数の下位語
ADDL GR2,=1 ;商のカウントアップ
JOV ADJ1 ;桁上り処理へジャンプ
JUMP CONT ;割り算実行
ADJ1 ADDL GR1,=1 ;桁上り処理実行
CONT SUBL GR6,0,GR3 ;引き算しながら割り算していく
JOV FIN
SUBL GR7,1,GR3 ;引き算しながら割り算していく
JOV ADJ2
JUMP LP
ADJ2 SUBL GR6,=1 ;繰り下がり処理
JOV FIN
JUMP LP
FIN POP GR7
POP GR6
RET
END
次にプログラム2、3では、割り算プログラムのプログラム1、DIVを利用して、
10進数の数字列に変換します。
GR1:#0000(変換する数の上位語)
GR2:#054D(変換する数の下位語、10進数で1357)
10000を16進数に直すと#2710、1000は#03E8、100は#0064、10は#000Aになります。
それをUDATに設定します。
結果を出力ウィンドウに表示します。
では、プログラム2を含めたステップ実行をして行きます。
丁寧にかつ、冗長な繰返しの所は要所要所省きながら行いました。
主記憶に1桁ずつ格納する結果領域KEKKAが用意されました。
数字列にする(割られる)数の上位語下位語が設定されました。
プログラム2、BTOD2が呼び出されました。
結果領域の先頭、末尾アドレスが入りました。
プログラム1、DIVが呼び出されました。
1357÷10000が実行されました。結果は0です。
プログラム2に戻りました。
商が数字列に変換されました。
結果領域の先頭アドレスに「0」が格納されました。
再びプログラム1、DIVが呼び出されました。
1357÷1000が実行されました。
1357から1000を引いて357、16進数に直すと#0165になりました。
商が1と求まりました。
数字列に変換され主記憶に格納されました。
357÷100が実行されました。
357-100で257、16進数で#0101が求まりました。
257-100で157、16進数で#009Dが求まりました。
157-100で57、16進数で#0039が求まりました。
商が3と求まりました。
主記憶に商の3が格納されました。
57は16進数で#0039です。
57÷10が実行されました。
57-10は47で、16進数では#002Fです。
47-10は37で16進数では#0025です。
37-10は27で16進数では#001Bです。
27-10は17で16進数では#0011です。
17-10は7です。
商が5と求まりました。
主記憶に格納されました。
7÷1が実行され、商の7が求められ、主記憶に格納されました。
出力結果です。
トレースに使ったノートはこちらになります。
;平成23年秋…割り算プログラム2
;呼び出し元のメインプログラム
MAIN START
RPUSH
LD GR1,=#0000 ;割られる数の上位語
LD GR2,=#054D ;その下位語で1357
LAD GR3,KEKKA ;結果領域先頭後
CALL BTOD2 ;プログラム2呼び出し
OUT KEKKA,LEN ;結果格納領域と文字数
RPOP
RET
KEKKA DS 5 ;結果格納領域
LEN DC 5 ;出力処理
;プログラム2
BTOD2
RPUSH
LD GR6,GR3
LAD GR7,4,GR3 ;結果格納領域の末尾アドレス
LAD GR3,UDAT ;除数の初期設定
LP2 CALL DIV ;プログラム1DIV呼び出し
OR GR2,=’0′ ;数字列に変換
ST GR2,0,GR6 ;10進数字1文字格納
CPL GR6,GR7 ;末尾まで処理したか
JZE FIN2
LAD GR6,1,GR6
LD GR1,GR4 ;割られる数の再設定
LD GR2,GR5 ;剰余をGR2へ
LAD GR3,2,GR3 ;割る数を2つ先へ
JUMP LP2
FIN2 RPOP
RET
UDAT DC 0
DC #2710
DC 0
DC #03E8
DC 0
DC #0064
DC 0
DC #000A
DC 0
DC 1
;プログラム1
DIV
PUSH 0,GR6
PUSH 0,GR7
LD GR6,GR1 ;割られる数の上位語
LD GR7,GR2 ;割られる数の下位語
LD GR1,=#FFFF ;商の初期化
LD GR2,=#FFFF
LP LD GR4,GR6 ;割られる数の上位語
LD GR5,GR7 ;割られる数の下位語
ADDL GR2,=1 ;商のカウントアップ
JOV ADJ1 ;桁上り処理へジャンプ
JUMP CONT ;割り算実行
ADJ1 ADDL GR1,=1 ;桁上り処理実行
CONT SUBL GR6,0,GR3 ;引き算しながら割り算していく
JOV FIN
SUBL GR7,1,GR3 ;引き算しながら割り算していく
JOV ADJ2
JUMP LP
ADJ2 SUBL GR6,=1 ;繰り下がり処理
JOV FIN
JUMP LP
FIN POP GR7
POP GR6
RET
END
最後にプログラム3です。
これは10ずつ割って行って工程が多いので、ステップ実行では無く、
一括実行で行います。
このシミュレーターの場合は、実行メニューから一括実行できます。
実行後の主記憶の状態です。
出力結果です。
トレースに使ったノートはこちらになります。
;平成23年秋…割り算プログラム3
;呼び出し元のメインプログラム
MAIN START
RPUSH
LD GR1,=#0000 ;割られる数の上位語
LD GR2,=#054D ;その下位語で1357
LAD GR3,KEKKA ;結果領域先頭後
CALL BTOD3 ;プログラム2呼び出し
OUT KEKKA,LEN ;結果格納領域と文字数
RPOP
RET
KEKKA DS 5 ;結果格納領域
LEN DC 5 ;出力処理
;プログラム3
BTOD3
RPUSH
LAD GR6,4,GR3 ;計算結果末尾のアドレス
LD GR7,GR3 ;計算結果先頭のアドレス
LAD GR3,DAT ;10で割って行く
LP3 CALL DIV ;プログラム1の呼び出し
OR GR5,=’0′ ;余りを数字列に変換
ST GR5,0,GR6 ;数字列を主記憶に格納する
CPL GR6,GR7 ;除算が先頭まで行ったか
JZE FIN3
LAD GR6,-1,GR6 ;除算を1つ前へ
JUMP LP3
FIN3 RPOP
RET
DAT DC 0
DC 10
;プログラム1
DIV
PUSH 0,GR6
PUSH 0,GR7
LD GR6,GR1 ;割られる数の上位語
LD GR7,GR2 ;割られる数の下位語
LD GR1,=#FFFF ;商の初期化
LD GR2,=#FFFF
LP LD GR4,GR6 ;割られる数の上位語
LD GR5,GR7 ;割られる数の下位語
ADDL GR2,=1 ;商のカウントアップ
JOV ADJ1 ;桁上り処理へジャンプ
JUMP CONT ;割り算実行
ADJ1 ADDL GR1,=1 ;桁上り処理実行
CONT SUBL GR6,0,GR3 ;引き算しながら割り算していく
JOV FIN
SUBL GR7,1,GR3 ;引き算しながら割り算していく
JOV ADJ2
JUMP LP
ADJ2 SUBL GR6,=1 ;繰り下がり処理
JOV FIN
JUMP LP
FIN POP GR7
POP GR6
RET
END
今度受けるので、自分の勉強になりました。
どなたかのお役に立てたらうれしいです。
この記事を書くのに4時間かかったので、
誰も見ていなかったら泣いちゃいます( ;∀;)
どなたか見ている人いますか?いたら手を振って下さい(=^・^=)