ニーモニックとは?命令セットを用いたプログラミングの問題解説

問題

下記(1)(2)の処理を計算機で実行するため、ニーモニック形式でプログラムを作成したい。
下表の命令セットとそれぞれの補足説明を用いてそれぞれのプログラムを作成せよ。

(1)\(A=(B+C*D)/E-(F*G+H)\)
ただし、右辺第1項、第2項の計算結果を中間変数\(tmp1,tmp2\)を格納して良い。

(2)\(A=B*C\)
※乗算命令MULTは使用せず、Cの回数分Bを足し算することを想定して実装すること。

命令セット意味
LOAD AメモリMに対し、Aに入っている値を格納する
ADD AメモリMに入っている値に対し、Aの値を足す
SUB AメモリMに入っている値に対し、Aの値を引く
DEC AAに入っている値から1を引く(デクリメント)
MULT AメモリMに入っている値に対し、Aを乗算する
DIB AメモリMに入っている値に対し、Aを除算する
STO AメモリMに入っている値をAに格納する
A JZERO xAに入っている値が0のとき、x行目の処理にジャンプする
JUMP 11行目にジャンプする
表1:ニーモニックの命令セット

ニーモニックの概要

C言語など、人間がプログラミングした言語を機械語に変換する前に作成する命令列を意味しています。

昨今、研究活動にて数値計算を行うために、プログラミングの需要が高まっています。

visual studioなど様々なエディタ上で、実行したい計算内容を私たちは様々な言語でプログラミングしています。

プログラミング完了後、コンパイルし、プログラムが何の気なしに実行されているように見えますが、実際計算機の中ではどういった処理が行われているのでしょうか。

実は、私たちが作成したプログラミング言語を直接機械語(0101の数値列)に変換しているわけでは無いです。

ニーモニックという命令セットの流れ(アセンブル言語)に変換してから機械語に変換しています。

C言語は決められた文法に基づいて記入するため、決められた命令セットに変換できる前提のもとに成り立っています。

プログラミングをしていると、コンパイルエラーが発生し、プログラムが実行できない場面があります。

これは、文法通りにコードを記載しなかったため、コンパイラが命令セットに変換できない=プログラムが実行できないという因果関係になっています。

命令セットを記載する順番

特に断りが無ければ、後置記法(逆ポーランド記法)を想定して記載します。

理由は、計算の順序が明確だからです。(以前の記事で詳しく説明しています。)

(1)で取り上げた数式\(A=(B+C*D)/E-(F*G+H)\)は中置記法です。

人間の目では分かりやすいものの、括弧()や、掛け算演算子*、割り算演算子/があったりと計算の順番に気を付けなければなりません。

計算機からすると、この違いが分かりません。

これを後置記法にすると、右辺の第1項は\(CD*B+E/\)になります。

このように、計算する順番から対象の変数を左から書いてやれば、計算機としては順番通りに実行するだけで良くなります。

また、スタック方式で処理を進めていくことができ、データ構造が簡潔になります。

解答例

(1)\(A=(B+C*D)/E-(F*G+H)\)

まず、\(B+C*D/E\)を計算し、結果を\(tmp1\)に格納 (下記ボックス1~5)

次に、\((F*G+H)\)を計算し、結果を\(tmp2\)に格納 (下記ボックス6~9)

最後に、\(tmp1\)に\(tmp2\)を引いて、結果をAにストアすれば良いです。(下記ボックス10~12)

後置記法だと、ABCD*+E/FG*H+-=になります。これを与えられた命令セットを用いて記載すると、下記になります。

コード
  1. LOAD C
  2. MULT D
  3. ADD B
  4. DIB E
  5. STD tmp1
  6. LOAD F
  7. MULT G
  8. ADD H
  9. STD tmp2
  10. LOAD tmp1
  11. SUB tmp2
  12. STO A

(2)\(A=B*C \)

forループを想定します。C言語で言うと、下記の書き方で実装すれば良いです。

for(i=1; i≦C ; i++){
 A=A+B
}

これをニーモニックで考えると、下記のように記載すれば同等になります。

コード
  1. C JZERO 9
  2. LOAD A
  3. ADD B
  4. STO A
  5. LOAD C
  6. DEC
  7. STO C
  8. JUMP 1
  9. HALT

※Aの初期値には0、B,Cにはある自然数が初期値として代入されている想定です。
もし初期値を明確にしたい場合は、1行目の前にLOAD 0、STO A などの処理の追記をお願いします。

補足:C言語、Pythonなどの高級言語を人間のプログラミングで使用する理由

問題を解くと、人間の手でもアセンブリ言語でプログラミングできることが分かります。ということは、高級言語なんて使用せずに、アセンブリ言語をそのまま使えば良いと考えるかもしれません。

しかし、そうはいきません。

(2)が特に顕著ですが、C言語だと3行で済むような処理をニーモニックの場合10行近く必要になります。

理由は、レジスタからメモリの転送処理の内容を逐次記載する必要があるからです。

今回はレジスタ一つだけなのでまだマシですが、大規模な数値解析や動的計画法の計算を行う場合、多数のレジスタが必要となります。

こうなると、レジスタに関わる処理の内容を人間が逐次記載していくことは、とても大変になります。

この手間を省くため、高級言語という新たな概念を持ち出し、レジスタとメモリ間の関係はあまり気にせずコードを記載できるようにした。という背景があります。

このような理由で、高級言語が好ましく使用されています。

(レジスタ-メモリ間の処理の記載は、最終的にコンパイラにお願いする仕組みです。)

最後に

本問は、東北大や、情報科学系の専門院試でよく出題されます。

ゴリゴリの情報系の研究室を志望される方は、是非チェックしたい内容です。

タイトルとURLをコピーしました