はじめに
こんにちは!iimonでフロントエンドエンジニアをしている「みよちゃん」です!
突然ですが自分はiimonで働きながら、通信制の大学(CS系)にも通っていて、今年から2年生になりました!その中で、現在アセンブリについて勉強しているのですが、普段の業務と全く関係のないように思える内容でも学びがあるな〜と思い記事にしてみました!
前提
今回使用する言語はCASLⅡです。CASLⅡはCOMETⅡという仮想CPU上で動作するアセンブリ言語です。動作を実際に確認したい方は、オンライン上のCASLシュミレータやシュミレータソフトを使用してください。
今回の記事では、COMETⅡの構成から始まり、プログラムがどのように動くか、条件分岐や繰り返し処理の記述まで一緒に見ていけたらと思います!
アセンブリとは
CPUによって実行されるソフトウェアは2進数で表現されています。CPUは2進数で表現されたプログラムの命令を一つずつ取り出して実行しています。2進数で書かれたプログラムのことを機械語と言います。人間がプログラムを実装する際に、0と1だけで表現するのは大変ですよね。。そこで、機械語の命令を記号で表現できるようにしたものをアセンブリ言語と言います。
この辺りでかなりややこしい名前が出てくるので、簡単に用語の説明をしたいと思います!
- アセンブリ言語: 機械語の命令を記号で表現したもの
- アセンブラ: アセンブリ言語で書かれたプログラムを機械語に翻訳するする翻訳機
- アセンブル: アセンブリ言語で書かれたプログラムを機械語に翻訳すること
つまり「アセンブリで書かれたプログラムをアセンブラでアセンブルする」ということです!
アセンブリを学ぶ意義
メリット
新しいことを学ぶ上で大事なことは、それを学ぶことで何を得られるかだと思うので、アセンブリを学ぶことのメリットをいくつか挙げていきたいと思います。
コンピュータの動作を深く理解できる
アセンブリを学ぶことで、CPUが命令を実行流れを理解することができます。
プログラムの動きを可視化できる
高級言語では見えない「メモリ管理」「レジスタ」「命令実行」を直接見ることができ、自分の書いたプログラムの動きをより細かく理解することができます。
アルゴリズムを考える訓練になる
アセンブリには、if文やループ文といった便利な機能はありません。全てを自分でプログラムする必要があります。そのため、普段は考えることのない深さでアルゴリズムを考える機会が得られます。
デメリット
学習コストが高い
メリットも記述しましたが、アセンブリには便利な構文はほぼほぼ存在しません。そのため高級言語と比較すると学習コストは高いと言えます。
業務ではまず使わない
業界によるとは思いますが、現在アセンブリを業務で使用することはかなり稀だと思います。そのため、「アセンブリを習得した⇒直接的に何かができるようになる」というわけではありません。
COMETⅡの構成
初めにCOMETⅡの構成を確認しながら、各構成要素が何をするのかを確認していきたいと思います!
レジスタ
- PR(プログラムレジスタ):次に実行される命令のアドレスが保存される(16bit)
- IR(命令レジスタ):解読・実行する命令が保存される(32bit)
- GR(汎用レジスタ):GR0-GR7までの汎用レジスタ(16bit)
- FR(フラグレジスタ): OverFlowFlag,SignFlag,ZeroFlagからなるレジスタ(3bit)
- MAR(メモリアドレスレジスタ):メモリを読み書きする際にアクセスするアドレスを指定するレジスタ(16bit)
- MDR(メモリデータレジスタ):メモリとデータのやり取りをするレジスタ(16bit)
レジスタ以外の構成要素
- ALU(演算装置):算術・論理・シフト・比較演算を行う
- Decoder(命令解読機):IRの命令を解読するモジュール
- Controller(制御装置):命令・実行のための制御を行うモジュール
- Bus(バス):レジスタやALUなどの間を間をデータが通る道
- Adder(アドレス加算機):命令アドレス部とインでキスレジスタの内容から有効アドレスを求める
CASLⅡのプログラム
次にCASLⅡの簡単なプログラムと、各命令の説明をしていきたいと思います。
PRG START LD GR1,A LD GR2,B ADDA GR1,GR2 ST GR1,ANS RET A DC 4 B DC 3 ANS DS 1 END
プログラムの全体感
プログラムの全体感について簡単に説明します
CASLⅡのプログラムは「ラベル」「命令」「オペランド」の三つから構成されます。
プログラムの先頭にはSTART命令を記述し、終わりにはEND命令を記述します。
命令: 実行したい命令を記述する
オペランド:命令実行に使用するデータを記述する
代表的な命令
ここからは、上のプログラムに出てきた命令を簡単に説明します。
DC(Define Constance)
メモリにオペランドのデータを定義する。
DS(Define Storage)
メモリにデータ領域を確保する。オペランドの数字分の領域を確保する。
LD(LoaD)
メモリの値を汎用レジスタに読み込む。第一オペランドにレジスタを、第二引数にデータのアドレスを指定する.
ADDA(ADDArithmetical)
算術的加算命令。第一オペランドの値に第二オペランドの値を符号付きのデータとして加算します
ST(STore)
第一オペランドのデータを第二オペランドのアドレス番地に格納します。
プログラムのトレース
それでは実際に先ほどのプログラムをトレースしたいと思います
まずPRとMARにはプログラムの開始部分のアドレス#0022が入っている。
- #0020からvalue#1010(GR1へのLD命令)を取り出しMDR→IRの前半へと格納する。
- PRの値を1加算しMARを経由してメモリにアクセス。第二オペランドであるAのアドレスを取得しMDRを経由してIRの後半へ格納する。
- IRのデータをDecoderへ渡し、前半部分はControllerへ後半部はAddderへ渡り、MARを介してメモリにアクセス。
- Aアドレス番地にあるデータを取得しALUを介してGR1へとデータを読み込む。
- PRとMARの値を1加算しMARを経由してメモリの#0022へアクセス
…繰り返し
というような順序でプログラムが進んでいきます。
すべてのプログラムをトレースすると莫大な量になってしまうので、文字にするのはここまでですが、基本的には同じ流れでプログラムが進むので、動画をみながらCPUの動きを理解していただければと思います。
今回のプログラムはAラベルのデータとBラベルのデータを加算した結果をANSラベルで確保していたメモリに格納するプログラムでした!
条件分岐やループ処理を含むプログラム
条件分岐とループ
アセンブリでは条件分岐や繰り返し処理をする際に、比較演算とFRの値を使用します。
比較演算
CPA:第一オペランドと第二オペランドの値を算術的に比較する
CPI:第一オペランドと第二オペランドの値を論理的に比較する
フラグレジスタ
演算の結果によって以下の3つのフラグが設定されます。
ZF:演算結果が0の時に1となる
OF:演算結果がオーバーフローした場合に1となる
SF:演算結果がマイナスの場合に1となる
フラグの値とJUMP命令
JUMP:条件に関係なく第一オペランドのアドレスまで移動する
JZE:ZFが1の場合第一オペランドのアドレスまで移動する
JMI:SFが1の場合に第一オペランドのアドレスまで移動する
JPL:SFとZFが0の場合に第一オペランドのアドレスまで移動する
条件分岐とループを含むプログラム
今回はAに格納されているデータとBに格納されているデータの積をANSに格納するプログラムを見てみましょう!
PRG START LD GR1,A LD GR2,B LAD GR3,0 LAD GR4,0 LOOP CPA GR4,GR2 JZE FIN ADDA GR3,GR1 LAD GR4,1,GR4 JUMP LOOP FIN ST GR3,ANS RET A DC 8 B DC 5 ANS DS 1 END
前提としてCASLⅡには乗算をする命令はありません。そのため、Aの値をB回加算することで積を求めていきます。
まず、AとBの値をそれぞれGR1,2にロードします。その後GR3,とGR4に数字の0を格納します
それぞれGR3はAの値を加算していくレジスタ、GR4はループ回数をカウントするレジスタとして使用します。
次にLOOP部分に着目してください。
- GR4とGR2の値を比較する
- ZRが1の場合はFINラベルへ移動
- GR3にGR1の値を算術的に加算する
- GR4の値を1加算する
- 1へ戻る
と言う処理内容になります。
FIN部分では、GR3の値をANSに格納して処理を終了します。
このように、比較演算とFRの値を使用することで、繰り返し処理や条件分岐を行います!
おわりに
今回の記事を通して、最初に挙げた「アセンブリを学ぶメリットを感じていただけたでしょうか?
COMETⅡは簡単な構造の仮想CPUなので、視覚的に表現することでCPUの動きについてなんとなく理解していただけたのではないかと思います!
3つ目の「アルゴリズムを考える訓練になる」については簡単なプログラムしか扱わなかったため、あまり実感できなかったかもしれませんが、プログラムが複雑になるとループや条件分岐の数も増え、アルゴリズムを考える機会になるのではないかと思います。
次回はスタックやインデックスを用いてもう少し複雑な処理を解説できればなと思っています。
最後になりますが、弊社ではエンジニアを募集しています!
この記事を読んで少しでも「いいな」と思っていただけたら、是非カジュアルにお話ししましょう!
最後まで読んでいただきありがとうございました!!!