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

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

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

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

この問題は、浮動小数点の加算を扱っています。
指数の大きい方に合わせて加算処理を行い、計算結果を正規化して主記憶に格納します。
加算される方がX、加算する方がYです。

Xを-0.1×2^2 →
10000000100000011000000000000000

Yを0.11×2^3 →
00000000100000101100000000000000

という具体例を元にトレースします。

主記憶に、X、Yの具体例と、結果格納用のZが入りました。

GR1、GR2、GR3に具体例と計算格納結果のアドレスが入りました。

ここから副プログラムのFADDにを呼び出します。
スタックに結果格納の先頭アドレスが退避されました。

GR4にXの符号部、指数部が入りました。

AND演算で指数部だけ取り出しました。

GR5にYの符号部、指数部が入りました。
AND演算で指数部だけを取り出しました。
(値は変わらず)

GR6にXの仮数部が読み込まれました。

GR7にYに仮数部が読み込まれました。

GR3にXの指数部Exが読み込まれました。

GR4のEx、GR5のEyが比較されました。

指数部の大きい方であるE7がGR4に読み込まれました。

GR5にExとEyの差が求まりました。

GR6に指数部を合わせるために、Xの仮数部であるMxが1ビット右シフトされました。

Xの符号がプラスかマイナスかチェックします。

Yの符号がプラスかマイナスかチェックします。

Yの仮数部のMyが読み込まれました。

MyマイナスMxが求まりました。

仮数部がゼロかチェックします。
ゼロでは無いです。
仮数部がマイナスなので、正規化済であり、終了処理に分岐します。

退避していた計算結果の先頭アドレスがGR3に戻りました。

計算結果の符号部と指数部、仮数部を格納しました。

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

プログラムはこちらになります。

MAIN START
RPUSH
LAD GR1,X
LAD GR2,Y
LAD GR3,Z
CALL FADD
RPOP
RET
X DC #8081 ;Xの16進数先頭、符号部、指数部
DC #8000 ;Xの16進数先頭+1、仮数部
Y DC #0082 ;Yの16進数先頭、符号部、指数部
DC #C000 ;Yの16進数先頭+1、仮数部
Z DS 2 ;計算結果2語分


FADD RPUSH ;Z←X+Y
PUSH 0,GR3 ;結果Zの格納領域の先頭番地を退避
LD GR4,0,GR1 ;Xの先頭を読み込む
AND GR4,=#00FF ;Ex:xの指数
LD GR5,0,GR2 ;Yの先頭を読み込む
AND GR5,=#00FF ;Ey:yの指数
LD GR6,1,GR1 ;Mx:Xの仮数(2語目)
LD GR7,1,GR2 ;My:Yの仮数(2語目)

;加算前の準備(指数を揃える)
;GR4←MAX(Ex,Ey)大きい方がGR4に入る
;GR6←調整済Mx , GR7←調整済My
LD GR3,GR4 ;Exを読み込む
CPL GR4,GR5 ;ExとEyどっちが大きいか比べている
JZE MADD ;Ex=Eyの場合。指数の調整が不要な場合の分岐命令
JMI BIGEY ;Ex=0,Y<=0の場合
SUBL GR5,GR7 ;Mz←調整済みMx-調整済My
JUMP SCHECK ;加算終了後の符号部チェックへ分岐

;Xがマイナスの時
XMINUS LD GR2,0,GR2 ;Yの符号の検査
JMI YMINUS ;Yもマイナスだった時の分岐
LD GR5,GR7 ;Myを読み込む
SUBL GR5,GR6 ;Y-X
JUMP SCHECK ;加算終了後の符号部チェックへ分岐

;Yがマイナスの時の処理
YMINUS OR GR4,=#8000 ;Szに符号部を設定

;加算実行
ADDMXY LD GR5,GR6 ;Mxを読み込む
ADDL GR5,GR7 ;Mz←調整済Mx + 調整済My
JOV ADJST ;桁上りがある時の正規化
JUMP NORM ;加算後の正規化へ
SCHECK JOV NEGMZ ;Mzの符号を検査
JUMP NORM ;加算後の正規化へ
NEGMZ OR GR4,=#8000 ;Szに符号部を設定
XOR GR5,=#FFFF ;Mz←-Mz
ADDL GR5,=1 ;Mz←-Mz完了

;加算結果の正規化
NORM LD GR5,GR5 ;仮数部のゼロチェック
JNZ LOOP ;ゼロ以外は分岐
LD GR4,=0 ;Szの符号
JUMP FIN
LOOP LD GR5,GR5 ;正規化完了??
JMI FIN ;マイナスだったら仮数部の最上位が1だから正規化終了
SLL GR5,1 ;左に詰めて正規化へ
SUBL GR4,=1 ;正規化処理分の指数部を1つ減らす
JUMP LOOP ;正規化出来るまで繰り返す

;桁上りの処理
ADJST SRL GR5,1 ;加算結果の仮数部を1つ右へ
OR GR5,=#8000 ;Mzの最上位ビットを1に設定
ADDA GR4,1 ;桁上り分
FIN POP GR3
ST GR4,0,GR3 ;結果Zの格納(符号部、指数部)
ST GR5,1,GR3 ;結果Zの格納(符号部、指数部)
RPOP
RET
END

今度受けるので、自分の勉強になりました。
どなたかのお役に立てたらうれしいです。
この記事の解説を理解するのに3時間以上かかったので、
誰も見ていなかったら泣いちゃいます( ;∀;)
どなたか見ている人いますか?いたら手を振って下さい(=^・^=)

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

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