この記事ではCASL2アセンブラ言語で、スタックを利用して文字列を逆に取り出すプログラムを作りました。
取り出す文字列は、インクジェットプリンターのインクで使われる「CMYK」です。
その「CMYK」の文字の並びを逆にした、「KYMC」をスタックに積み上げて、スタックの仕組みを利用して「CMYK」にして出力します。
この記事では、こちらのWebのシミュレーターを使っています。
ダウンロードすることなく、素早くアセンブラの勉強が出来る、私が使った中で1番便利なシミュレーターです。
CMYKについて基本情報技術者試験(FE)を受けられる方は既にご存知だと思いますが、簡単にお話しすると、インクジェットプリンターで使われているインクです。
C(シアン)、M(マゼンタ)、Y(イエロー)、K(ブラック)のことで、もう少し詳しく知りたい方は、こちらの外部記事が分かりやすいです。
この配列BEFOREは、逆から読むとCMYKになります。
スタックと言う、イメージ的に積み木みたいな仕組みを使って、
配列BEFOREの「KYMC」を配列AFTERに「CMYK」と出力されるように格納します。
配列BEFOREのすぐ後にあるのは、目印に使う配列ENDでゼロが格納されています。
では、積み木みたいなスタックに積まれて行く様子を図にします。
スタックに積む時にはPUSH命令を使います。
文字の処理が終わったかどうかの目印に、「0(ゼロ)」を使いますので、最初に0をスタックに積みます。
スタックにはPUSH命令で、このように1文字ずつ積み上げていき、取り出す時には
POP命令を使って、一番上(最後に積み上げた文字)から順に取り出します。
取り出した文字を出力用の配列AFTERに格納します。
すると、「KYMC」が「CMYK」になって出力されます。
元の文字列「KYMC」は配列BEFORE[]に入っています。
スタックを使って出力用に格納する配列はAFTER[]です。
どちらも、GR1を使ってアドレスを指し示します。
GR2は、文字列をスタックに積んだり取り出したりする時に使います。
また、GR2は、出力用文字列に格納する時にも使います。
CMYKの文字コードはこちらになります。
‘K’…「004B」
‘Y’…「0059」
‘M’…「004D」
‘C’…「0043」
文字コードについてはこちらの外部記事が分かりやすいです。
それでは、プログラムを掲載致します。
TEST START
RPUSH
LAD GR2,0 ;GR2に目印の0を設定
PUSH 0,GR2 ;スタックにGR2の値を積む
LAD GR1,BEFORE ;GR1に配列BEFOREの先頭アドレスを設定
OUT BEFORE,LEN ;配列BEFOREを出力
;<<スタックに積むループPUSH>>
LOOPPUSH LD GR2,0,GR1 ;GR2に配列BEFOREのGR1が指し示す文字を読み込む
CPL GR2,=0 ;目印の0まで到達したか、GR2の文字と目印0を比較する
JZE PREPOP ;目印0まで到達したら配列AFTERの準備でPREPOPまで分岐する
PUSH 0,GR2 ;処理中の場合は読み込んだ文字をスタックに積む
LAD GR1,1,GR1 ;配列BEFOREの位置を1つ先に進めるのでGR1をインクリメントする
JUMP LOOPPUSH ;読み込みとスタックに積む処理が完了するまでLOOPPUSHを繰り返す
;配列AFTERの出力準備
PREPOP LAD GR1,AFTER ;GR1に配列AFTERのアドレスを設定
;<<スタックから取り出すループPOP>>
LOOPPOP POP GR2 ;スタックから1文字取り出してGR2に格納
CPL GR2,=0 ;文字の取り出しが最後の目印まで到達したか確認
JZE FIN ;等しい(取り出し処理が終了)場合はFINラベルへ
ST GR2,0,GR1 ;処理中ならGR2で取り出した文字をGR1を使って配列AFTERに格納
LAD GR1,1,GR1 ;配列AFTERの位置を1つ先に進めるのでGR1をインクリメントする
JUMP LOOPPOP ;出力処理が終わるまでLOOPPOPを繰り返す
FIN OUT AFTER,LEN ;配列AFTERを出力する
RPOP
RET
BEFORE DC 'KYMC'
END DC 0
AFTER DS 100
LEN DC 4
END
ここから、実際にシミュレーターを動かして見て行きます。
GR2に目印となる0を設定し、スタックにその0を積みます。
GR1に配列BEFOREの先頭アドレスを設定します。
OUT命令で元の文字の配列BEFOREをコンソールに出力します。
スタックにPUSHするループ、LOOPPUSHに入り、配列BEFOREの先頭文字の‘K’…「004B」をGR2に読み込みます。
GR2のKと目印の0を比較します。
等しくないのでループを続行します。
スタックに‘K’…「004B」を積みます。
配列BEFOREの位置を1つ進めるのでGR1をインクリメントします。
ループLOOPPUSHを繰り返します。
GR2に‘Y’…「0059」を読み込みます。
Yと目印の0を比較します。
等しくないのでループを続けます。
スタックに‘Y’…「0059」を積みます。
配列BEFOREを1つ先に進めるので、GR1をインクリメントします。
ループLOOPPUSHを繰り返します。
GR2に‘M’…「004D」を読み込みます。
Mと目印の0を比較します。
等しくないのでループを続けます。
スタックに‘M’…「004D」を積みます。
配列BEFOREを1つ先に進めるので、GR1をインクリメントします。
ループLOOPPUSHを繰り返します。
GR2に‘C’…「0043」を読み込みます。
Cと目印の0を比較します。
等しくないのでループを続けます。
スタックに‘C’…「0043」を積みます。
配列BEFOREを1つ先に進めるので、GR1をインクリメントします。
ループLOOPPUSHを繰り返します。
GR2に‘目印’、配列ENDの「0」を読み込みます。
GR2と目印の0を比較します。
等しいので、ゼロフラグが立ちました。
分岐命令JZEで、ループを抜けて配列AFTERの出力準備のPREPOPに分岐して、GR1に配列AFTERの先頭アドレスを設定します。
今度は取り出しループのLOOPPOPに入り、スタックから一番上に積まれた‘C’…「0043」をPOP命令で取り出します。
スタックからGR2に取り出された‘C’…「0043」と目印の0を比較します。
等しくないのでループを続けます。
GR2に取り出された‘C’…「0043」を配列AFTERに格納します。
配列AFTERを1つ先に進めるのでGR1をインクリメントします。
ループLOOPPOPに戻ります。
GR2にスタックから一番上に積まれている‘M’…「004D」をPOP命令で取り出します。
スタックからGR2に取り出された‘M’…「004D」と目印の0を比較します。
等しくないのでループを続けます。
GR2に取り出された‘M’…「004D」を配列AFTERに格納します。
配列AFTERを1つ先に進めるのでGR1をインクリメントします。
ループLOOPPOPに戻ります。
スタックから一番上に積まれている‘Y’…「0059」をPOP命令で取り出します。
スタックからGR2に取り出された‘Y’…「0059」と目印の0を比較します。
等しくないのでループを続けます。
GR2に取り出された‘Y’…「0059」を配列AFTERに格納します。
配列AFTERを1つ先に進めるのでGR1をインクリメントします。
ループLOOPPOPに戻ります。
スタックから一番上に積まれている‘K’…「004B」をPOP命令で取り出します。
スタックからGR2に取り出された‘K’…「004B」と目印の0を比較します。
等しくないのでループを続けます。
GR2に取り出された‘K’…「004B」を配列AFTERに格納します。
配列AFTERを1つ先に進めるのでGR1をインクリメントします。
ループLOOPPOPに戻ります。
スタックから最後に残った目印の「0」をPOP命令で取り出します。
スタックからGR2に取り出された0と目印の0を比較します。
等しいのでJZE命令でFINラベルに分岐します。
コンソールに配列AFTERを出力します。
お疲れ様でした。
ここで一旦、写真で休憩を挟みます。
目白庭園という日本庭園の紅葉ライトアップです。
ここから、復習&アウトプットタイムです!!
下記のコードをシミュレーターにコピペして、コメントを頼りに先ほどのコードを覚えているか入力して見て下さい。
上手く動いたら、値などを好きなように変えて動かして見て下さい。
この復習は学習直後は勿論、明日など少し日を開けて行うと、更に効果的です!!
このコードでも、推しがいる方はあなたの推しの名前をスタックを使って取り出してみると面白いと思います。
TEST START
RPUSH
;GR2に目印の0を設定
;スタックにGR2の値を積む
;GR1に配列BEFOREの先頭アドレスを設定
;配列BEFOREを出力
;<<スタックに積むループPUSH>>
;GR2に配列BEFOREのGR1が指し示す文字を読み込む
;目印の0まで到達したか、GR2の文字と目印0を比較する
;目印0まで到達したら配列AFTERの準備でPREPOPまで分岐する
;処理中の場合は読み込んだ文字をスタックに積む
;配列BEFOREの位置を1つ先に進めるのでGR1をインクリメントする
;読み込みとスタックに積む処理が完了するまでLOOPPUSHを繰り返す
;配列AFTERの出力準備
;GR1に配列AFTERのアドレスを設定
;<<スタックから取り出すループPOP>>
;スタックから1文字取り出してGR2に格納
;文字の取り出しが最後の目印まで到達したか確認
;等しい(取り出し処理が終了)場合はFINラベルへ
;処理中ならGR2で取り出した文字をGR1を使って配列AFTERに格納
;配列AFTERの位置を1つ先に進めるのでGR1をインクリメントする
;出力処理が終わるまでLOOPPOPを繰り返す
;配列AFTERを出力する
RPOP
RET
BEFORE DC 'KYMC'
END DC 0
AFTER DS 100
LEN DC 4
END
皆さま、大変お疲れ様でした。
この記事最後のブレイクタイムPhotoは・・・
仕事や勉強のリフレッシュに、趣味で写真を撮っておりますので、宜しかったら フォトストック写真ACさん の投稿もご覧頂けますと、大変嬉しい限りでございます!!
こちら、無料の「ダウンロードユーザー」に登録して頂けると、無料で写真のダウンロードが可能になります。
※ 先にGoogleアカウントを作成して頂くと、登録が ラク です♪
最後までご精読、誠にありがとうございました!!
自己紹介
アセンブラ自作サンプルとFE出題範囲のアリゴリズムへ
アセンブラ過去問プログラムへ
プログラミング未経験者はアセンブラと表計算どっち!?
基本情報技術者試験トップへ
午前免除試験
午後試験のオススメ本
スコアレポート