戻る

アセンブリ言語とは?

一般的なプログラミング言語(以降、高級言語とする)は多少の制約はあるにせよ、基本的にはCPUにはあまり影響されない。
「C」などの場合はポインタなどはハードウェアの仕様に依存するため、ライブラリでそのあたりをある程度はカバーされている。
アセンブリ言語はターゲットがそれぞれの「マイクロプロセッサ」に依存する。
「8086」に対して書かれたプログラムは「68000」では全く使えない、ということである。
これが高級言語と大きく異なる点である。

また、「インタプリタ」や「コンパイラ」とは違い、「アセンブラ」は命令(ニーモニック)群をマシン語(機械語)に変換するものである。
(コンパイラも変換といえば変換だが、コンパイラは分割コンパイルや最適化などの動作があるため、直接マシン語に変換しないものが一般的である)

では、アセンブリ言語ではどのようなプログラミングをすることになるのか、ということになる。
例えば高級言語では処理が遅くなるような処理を記述したり、直接ハードウェアを操作するような場合はアセンブリ言語を使うことになる。

アセンブリ言語は高級言語とは違い、「変数」や「関数」などといったものは存在しない。
あるものはプロセッサに依存したレジスタ(一時記憶装置)やメモリへのアクセス、プログラムの制御などである。
つまり、「画面に表示する」だとか「音楽を演奏する」というような命令はない。
そのような動作そのものを書くことができる、というものなのだ。

例えるなら、人が「文字を書く」という動作を考えよう。
人が文字を書く行為そのものは意識をしないでただその文字を「書く」だけである。
しかし、これを脳が命令しているレベルで考えてみると

  1. 筆記用具と用紙を探す
  2. 筆記用具を握る
  3. 文字を描くために用紙の上で筆記用具を動かす

という動作を行うために脳が記憶を元に文字を思い浮かべて、腕や指に命令を出しているわけである。
これを行っているのが、プロセッサにおいてはアセンブリ言語だと思うと理解が多少はしやすいのではないだろうか。

高級言語で文字を表示する、という処理は大抵の場合、命令もしくは関数で用意されている。
「BASIC」でいうところの「PRINT」、「C」でいうところの「printf」などである。

しかし、アセンブリ言語では前述のようにそのような命令はない。
従って

  1. 表示する文字のデータを用意する
  2. 表示する場所を指定する
  3. 文字のデータを指定された場所に転送する

というような感じになるわけである。

このようなメモリとのデータのやり取りはアセンブリ言語の基本である。
「C」や「C++」でよく使われるポインタの概念はまさにこれである。

アセンブラではデータをレジスタにロード(読み込み)をするためにアドレスをレジスタに指定する。
そして、そのレジスタに格納されたアドレスにあるメモリ上のデータをロードする。
その際、インデックスなどで指定先を変更する動作が「C」のポインタの概念と非常に近い。

アセンブリ言語の場合はいくつかの方法がある。
気を付けなければならないのはプロセッサによってその方法は異なるということである。
もちろん概念的には共通するものが多いが、その書式などはプロセッサの設計やその思想によって大きく違いがある。

例えば「6809」の場合は

LDA   $0000     # メモリの値をアキュムレータ「A」にロード

同じMotorola系列でも「68000」の場合は

lea.l  $00000000,a0  # アドレスをアドレスレジスタ「a0」に格納
move.b (a0),d0    # アドレスレジスタ「a0」が示すメモリの値をデータレジスタ「d0」に転送

となる。
「68000」はデータとアドレスでそれぞれレジスタが異なるので、2段階必要になる。

これが、80系の「Z80」になると

LD   A,(0000H)   # メモリの値をアキュムレータ「A」にロード

と、このように似てはいるが書式は全て異なる形になる。
(値が「0」の場合、0クリアを意味するオペランドを使うほうが望ましいケースだが、今回はアドレス値という意味合いを強調するためにロードを使っている)

68系と80系の16進数アドレス表記にも違いがある。
上記の例で示した通り68系は「$〜」、80系は「〜H」となる。
(Microsoft製BASICの場合は「&H〜」、CやC++などでは「0x〜」という表記である)

これらはプロセッサというよりはアセンブリ言語の仕様によって異なる。
また、場合によっては2進数や10進数、8進数などが記述できるものもある。

ところで「C」を知っている人は「68000」の書き方で気づいたかもしれない。
「lea」がポインタ指定で「move」でポインタの中身を呼び出している、ということになる。
なので、「68000」は特に「C」のプログラマにとってはとっつきやすいプロセッサであったりする。

アセンブリ言語の基本はデータをレジスタ、メモリでやり取りする。
そしてレジスタで演算して結果に応じて処理を行うという形になる。

こういってしまえば高級言語とさほど変わりはない。
だがその制限がプロセッサに依存する、というのが異なる。

しかし、基本は一緒である。
ただ、処理できるレベルが基本的なことになるだけなのだ。

例えば、文字列を表示するためにはどうすればよいか。
答えは簡単で、文字列を格納したアドレスから文字列表示のためのサブルーチンに転送する。
ではそのサブルーチンはどうすればよいか。
引き渡された文字列を画像表示用のRAM(V-RAM)に渡したりするわけである。

このような動作を組み合わせて、高級言語で行うような処理を構築していく。
実際にはOSレベルでライブラリが用意されていたりするので、そこを呼び出すだけになる。
こうなってくると高級言語とさほど変わらないといっても言い過ぎではないのかもしれない。


[TOPに戻る]