平成26秋の過去問問12 アセンブラ のプログラミング(コメント、トレースのノート付き)

この記事では、過去問のアセンブラの問題に載っているプログラムを実際に自分の環境で作成して動かすのに使ったコードと、トレースのノートを掲載しています。
この記事を通してアセンブラだけでなくアルゴリズムのトレース力向上にもお役立て下さい。

アセンブラ過去問プログラミング
アセンブラ自作サンプルへ
基本情報技術者試験トップへ
令和2年度(令和3年1月合格報告)

シミュレーターと過去問を解くまでの勉強に使った参考書はこちらです
バブルソートの自作サンプルプログラム

この問題のブログ記事を書く前に久々にサザエさんを見たら、ほっこり出来た上に、最後のじゃんけん、勝ちました!!(どやっ(=^・^=)!!)という訳で、ノリノリで過去問のプログラミングとトレース行きます!!
今回はバブルソートの問題です。


主プログラムで配列ARRAYの先頭アドレス(ARRAY+0)をGR1に設定して、
ソートする数をGR2に設定します。ソート前、後でOUT命令で出力する様にしたので、文字数4をOLEN(OUT LENの略)でGR2に読み込ませるようにしました。
具体例は設問2の例を使います。
設定が終わったら、プログラミング1のSORTを呼び出します。
トレースしながら設問1、2同時に答えられるのでやって行きます。

配列ARRAYに「2、4、1、3」が格納され、それを「1、2、3、4」に並び変えながら設問に回答します。
普通のバブルソートはおケツからソートしますが、この問題では頭からソートしていきます。「2、4」の大小関係は小さい方が前だからそのまま交換無し、交換が無い時に「空欄a」で分岐して交換処理を飛ばし、
次に「4、1」の大小関係の比較…とと続いて行きます。
それではプログラミングをして、実際にシミュレーターで動かしながらトレースをやって行きます。

ARRAYの先頭アドレスARRAY+0(我が家の環境でのアドレス値)と、バブルソートを行う数値の数の4が入りました。
プログラム1が呼び出されました。

GR2の外ループカウンタが1つ減って4から3になりました。

外ループ、並び替えのターンの区切り線を見やすいように出力しました。

内ループカウンタがGR3に入りました。

GR4に、ARRAYの先頭アドレスARRAY+0の我が家の環境でのアドレスが退避されました。

ARRAY「2、4、1、3」の「2」がGR5に退避されました。

CPLで「2」と「4」が比べられて、2の方が小さいのでSFに1が入りました。・・・・7行目の1回目

並び替えの必要が無いので、空欄aの分岐により並び替えの処理を飛ばしてCONTに分岐しました。
GR3の内ループのカウンタが1つ減って、GR4のアドレスがARRAY+1になりました。

内ループ1回目を終えた状態が入りました。

ループ2へ戻って次の比較をします。
「2、4、1、3」の「4」がGR5に退避されました。

CPLで「4」と「1」が比べられて、4の方が大きいのでSFに0が入りました。・・・・7行目の2回目
その為2つの要素の入れ替えは飛ばさずに入れ替え処理を行います。

「1」がGR6に退避されました。

「4」が1つ後ろに格納されました。
「1」が1つ前に格納して交換が終わりました。・・・・11行目の1回目
GR3の内ループカウンタが1つ減って、GR4のアドレスがARRAY+2になりました。

現在の配列の様子が2行目に出力されました。
「2、1、4、3」になっています。

ループ2へ戻って次の比較をします。
「2、1、4、3」の「4」がGR5に退避されました。

CPLで「4」と「3」が比べられて、4の方が大きいのでSFに0が入りました。・・・・7行目の3回目
その為2つの要素の入れ替えは飛ばさずに入れ替え処理を行います。

「3」がGR6に退避されました。

「4」が1つ後ろに格納されました。
「3」が1つ前に格納して交換が終わりました。・・・・11行目の2回目
GR3の内ループカウンタが1つ減って0になり、GR4のアドレスがARRAY+3になりました。

現在の配列の様子が2行目に出力されました。
「2、1、3、4」になっています。

GR3の内ループのカウンタが0になったので、次のターンに行きます。
GR2の外ループカウンタが1つ減りました。

ループ1へ戻って次のターン用に区切り線を引きました。

外ループカウンタの2がうちループカウンタに入りました。

GR4に配列の先頭アドレスARRAY+0が入りました。

「2、1、3、4」の「2」がGR5に退避されました。

CPLで「2」と「1」が比べられて、2の方が大きいのでSFに0が入りました。・・・・7行目の4回目
その為2つの要素の入れ替えは飛ばさずに入れ替え処理を行います。

GR6に「1」が退避されました。

「2」が後ろに行って、退避した「1」が前に格納されました。・・・・11行目の3回目、設問2空欄「d」は3回でした。
GR4のアドレスが1つ後ろのARRAY+1、GR3の内ループカウンタが1つ減りました。

現在の配列の状態が出力されました。
「1、2、3、4」

ループ2に戻りました。
CPLで「2」と「3」が比べられて、2の方が小さいのでSFに1が入りました。・・・・7行目の5回目

並べ替えは行わずにCONTへ分岐して、GR4のアドレスがARRAY+2になって、内ループのカウンタが1つ減りました。

出力結果は変わらず「1、2、3、4」です。

内ループが0になったので、外ループが1つ減りました。

次のターンへ処理するのでループ1へ分岐します。
区切り線が引かれました。

GR2の外ループのカウンタがGR3の内ループのカウンタに入りました。

GR4に先頭アドレスARRAY+0が入りました。

「1、2、3、4」の「1」がGR5に退避され比較します。・・・・7行目の6回目
設問2空欄「c」は6回でした。

並び替えは行わないのでCONTに分岐します。
GR4のアドレスがARRAY+1になってGR3の内ループカウンタが0になりました。

出力結果です。

内、外ループカウンタ、共に0になりました。

プログラム1が終わりました。

;平成26年秋バブルソート
;主プログラム
MAIN START
RPUSH
LAD GR1,ARRAY ;GR1に配列ARRAYの先頭アドレスを設定する
LD GR2,OLEN ;GR2に並び替える数4を読み込む
CALL SORT ;プログラム1SORTを呼ぶ
RPOP
RET
ARRAY DC ‘2413’
OLEN DC 4
BUF DS 256
;プログラム1SORT
SORT RPUSH
SUBA GR2,=1 ;ループのカウンタ1を設定(外ループ)
LOOP1 OUT LINE,LLEN ;ターンの区切り線
LD GR3,GR2 ;ループのカウンタ2を設定(内ループ)
LD GR4,GR1 ;GR4←比較する要素のアドレス
LOOP2 LD GR5,0,GR4 ;現在のアドレス内の数を取り出す
CPL GR5,1,GR4 ;↑と次の要素を比較‥‥設問2「c」
JMI CONT ;空欄「a」交換が発生しない場合に分岐
LD GR6,1,GR4 ;2つの要素を入れ替え。後ろの要素をGR6に退避
ST GR5,1,GR4 ;現在の要素を後ろへ格納
ST GR6,0,GR4 ;退避した要素を前に格納
CONT ADDA GR4,=1 ;比較する位置を後ろに移動
SUBA GR3,=1 ;内ループカウンタを減らす
OUT ARRAY,OLEN ;途中の並び替えを出力
JPL LOOP2 ;次の比較へ
SUBA GR2,=1 ;外ループを減らして次のターンへ
JPL LOOP1 ;空欄「b」残っている場合はLOOP1へ
RPOP
RET
LINE DC ‘———-‘
LLEN DC 10
END

では、設問3へ行きます。
具体例では、入力ウィンドウでBUFに4桁の5つの数値を出力してそれを数字列から数値にして並び替えて出力します。
1つ目の数字列は「298」「3(文字数)」と入力します。
これを2進化10進数、「298」でしたら「0298」なので、
0…「0000」
2…「0010」
9…「1001」
8…「1000」
と変換して、ARRAY+0に格納します。
次は「30」「2(文字数)」を入力して同じように変換してARRAY+1に格納…というのを5つ目の数字をARRAY+4に格納する
所まで行います。

GR1にARRAY+0を読み込んでプログラム1のSORTを呼び出します。

並び替え終わったら、一番小さい数字を数字列(文字)に変換して出力します。
変換の仕方は000Fと論理積を取り、文字コードを+30して文字にして、それをBUFに格納します。
4桁終わったら次の数字列に行きます。

数字列の入力で、-1が入ったら入力処理を終えるようにします。

これまでの道筋をノートにまとめました。

プログラム2を作りましたので動かして見ます。

まだ数字を1つも入力していないので、GR2に0が入ります。

まず、最初の数値「298」を入力します。

Enterを押して入力を終えます。

「298」は3桁なのでGR0に桁数の3が入りました。

配列に格納される内容が初期化されました。
あとで数字列から数値に変換する時に使います。

GR4にBUFのアドレスが入りました。
数値化の変換する位置の指定に使います。

「298」の「2」がGR5に読み込まれました。

「2」が数値に変換されました。

次の桁用に左シフトされました。
GR3は0なので値は変わりません。

2進化10進数に変換する為にGR5の0002がGR3に加算されました。

「298」の「9」を読むために進めました。

GROの処理待ち桁が1つ減りました。

ループ4に戻ります。

以下、「9」、「8」が読み込まれる処理を行います。
9が数値化され、格納される前に、GR3が4ビット右へシフトされました。
このシミュレーターは16進数表示にしてあるので、2進数の4桁で16進数の1桁が左に1つ移動したことになります。
0002から0020に移動して右端が0になりました。

0になった所に「9」が入って0029になりました。

「298」の「8」が読み込まれて数値化されました。
0029から0290に左にシフトされました。

290の空いた0の所に「8」が入って0298になりました。

数値変換処理が終わって、配列ARRAY+0に格納されました。

以上の処理が終わったので、処理済みの数字列の数が1つ加算されました。

同様に、「30」、「9」、「3240」、「508」を処理します。
(略)

何も入力せずEnterで5つの数字列を入力する処理を追えました。
以降、ソート処理になります。

CALLでプロうグラム1のソートを呼び出して、5つの数字列をバブルソートします。
プログラム1の所は省略します。
(略)
「9」、「30」、「298」、「508」、「3240」に並び替えらえれました。

主プログラムに戻りました。
バブルソートによる並べ替えが終わって出力処理に入ります。
GR4に空白文字が読み込まれました。

最も小さい「9」から数字列に変換します。
GR3に入りました。

下一桁が取り出され、(空欄e)数字列に変換されました。

この「9」がバッファ4桁のうちの1番右BUF+3に入りました。

0009が右にシフトされ、0000になりました。
(空欄f)
なので4桁分3桁空いてしまったので(0009だから、「△△△9」にする。△は空白。)ループ7で3つ分の△を埋める空白処理を行います。

空白を埋める処理が終わって、一番小さい数が出力されました。

以下、同様の処理をするので、ステップ実行から一括実行に切り替えて一気に表示します。

昇順に表示されました。

これで終わりましたので、プログラム2とノートを掲載します。

;平成26年秋バブルソート
;プログラム2主プログラム
MAIN START
RPUSH
LD GR2,=0 ;数字列のカウンタを初期化
LOOP3 IN BUF,ILEN ;数字列の長さ
LD GR0,ILEN ;GR0に長さを読み込んで配列格納の位置に使用する
JZE EOF ;何も入れなかったら入力処理を終える
LD GR3,=0 ;配列に格納する内容を初期化
LAD GR4,BUF ;GR4に入力に使用した領域BUFの先頭アドレスを入れる
LOOP4 LD GR5,0,GR4 ;GR5←数字
AND GR5,=#000F ;数字の数値化
SLL GR3,4 ;処理済の内容を桁上げ
OR GR3,GR5 ;空いた右端4ビットに数値を格納
ADDA GR4,=1 ;アドレスを1つ先へ
SUBA GR0,=1 ;格納する桁を1つ前へ
JNZ LOOP4 ;桁分の処理がある場合はLOOP4へ
ST GR3,ARRAY,GR2 ;ソート用に格納
ADDA GR2,=1 ;ソート用に格納する位置を1つ進める
JUMP LOOP3
EOF LAD GR1,ARRAY ;マイナスが入力されたらソートへ
CALL SORT
LD GR4,=’ ‘ ;空白文字を設定(4桁に満たない場合)
LOOP5 LD GR0,0,GR1 ;出力用に読み込む
LD GR5,=3 ;ループのカウンタを設定
LOOP6 LD GR3,GR0 ;数字に変換するために退避
AND GR3,=#000F ;「空欄e」下一桁を取り出す
OR GR3,=#0030 ;数値の数字化
ST GR3,BUF,GR5 ;バッファに数字を設定
SUBA GR5,=1 ;バッファ格納位置を1つ前へ移動
JMI WRITE ;格納が終わったら出力へ
SRL GR0,4 ;「空欄f」上の桁の数字化用に右シフト
JNZ LOOP6
LOOP7 ST GR4,BUF,GR5 ;バッファに空白を設定
SUBA GR5,=1
JMI WRITE
JUMP LOOP7
WRITE OUT BUF,OLEN ;4桁出力
LAD GR1,1,GR1 ;次の数値の数字化と出力処理へ
SUBA GR2,=1 ;処理待ち分を減らす
JNZ LOOP5
RPOP
RET
BUF DS 256 ;入出力領域
ILEN DS 1 ;入力桁数
OLEN DC 4 ;4文字出力
ARRAY DS 100 ;バブルソート用
;プログラム1SORT
SORT RPUSH
SUBA GR2,=1 ;ループのカウンタ1を設定(外ループ)
LOOP1
LD GR3,GR2 ;ループのカウンタ2を設定(内ループ)
LD GR4,GR1 ;GR4←比較する要素のアドレス
LOOP2 LD GR5,0,GR4 ;現在のアドレス内の数を取り出す
CPL GR5,1,GR4 ;↑と次の要素を比較‥‥設問2「c」
JMI CONT ;空欄「a」交換が発生しない場合に分岐
LD GR6,1,GR4 ;2つの要素を入れ替え。後ろの要素をGR6に退避
ST GR5,1,GR4 ;現在の要素を後ろへ格納
ST GR6,0,GR4 ;退避した要素を前に格納
CONT ADDA GR4,=1 ;比較する位置を後ろに移動
SUBA GR3,=1 ;内ループカウンタを減らす
JPL LOOP2 ;次の比較へ
SUBA GR2,=1 ;外ループを減らして次のターンへ
JPL LOOP1 ;空欄「b」残っている場合はLOOP1へ
RPOP
RET
END

今度受けるので、自分の勉強になりました。
どなたかのお役に立てたらうれしいです。
頑張って書いたので、誰も見ていなかったら泣いちゃいます( ;∀;)
どなたか見ている人いますか?いたら手を振って下さい(=^・^=)
要領悪すぎにゃ~~~~~~( ;∀;)(=^・^=)( ;∀;) (^O^)/

シミュレーターと過去問を解くまでの勉強に使った参考書はこちらです
バブルソートの自作サンプルプログラム

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

モバイルバージョンを終了