矢沢久雄 グレープシティ アドバイザリースタッフ

 プログラマであってもなくても,コンピュータに関わる人なら,だれでも一度はアセンブラを学んでいただきたいと思います。アセンブラは,コンピュータのハードウエア的な動作を生々しく記述するプログラミング言語です。アセンブラを学ぶことで,CPU(プロセサとも呼ぶ)の機能やOSの役割などが手に取るように見えてきます。すなわち,コンピュータに何ができるのかが分かるのです。

図1●高水準言語と低水準言語

 アセンブラとマシン語のことを「低水準言語」と呼びます。一方,COBOL,BASIC,Pascal,C言語,C++,Java,C#などのプログラミング言語を「高水準言語」と呼びます。低水準とは,コンピュータの生の動作に近いという意味で,高水準とは,人間の感覚に近い(コンピュータの生の動作からは遠い)という意味です。高水準言語を使えば,コンピュータのハードウエアの知識がなくてもプログラムが作れます。高水準言語のプログラムは,アセンブラのプログラムより行数が少なく,効率的に作成できます。そのため,現在ではアセンブラはめったに使われず,ほとんどのプログラマが高水準言語を使っています。

 そうであっても,アセンブラの知識は,覚えて損のないどころか,必ず覚えておくべき課題だと言えます。プログラマがアセンブラを学べば,プログラミングのテクニックが大いに向上し,コンピュータの生の動作を意識した無駄のないプログラム(実行速度が速く,サイズがコンパクトなプログラム)を高水準言語でも作れるようになります。プログラマでない人がアセンブラを学ぶと,コンピュータへの理解と興味が大いに深まります(図1[拡大表示])。

 この連載では,アセンブラの概要と基本的なプログラミング手法を紹介します。プログラミング経験のない人にも理解できるようにやさしく説明しますので,この機会にアセンブラの知識を身に付けて,コンピュータとプログラムの本当の姿を知ってください。

●アセンブラとは何か?

 では,アセンブラとは何かを説明しましょう。いきなりですが,リスト1を見てください。これは,アセンブラではなく,C言語で記述されたプログラムです。キー入力された2つの値を加算した結果をディスプレイに表示します。プログラムの内容を理解する必要はありません。何やら英語と数学を混ぜ合わせたような文が羅列されていることだけに注目してください。

リスト1●C言語で記述されたプログラム
#include

void main()
{
  int a,b,ans;
  scanf("%d",&a);
  scanf("%d",&b);
  ans = a + b;
  printf("%d\n",ans);
}

図2●Kasan.exeの内容

 コンピュータの頭脳であるCPUは,C言語のプログラムを解釈・実行できるのでしょうか? 答えはNOです。C言語は,人間の言葉(英語と数学)に近い表現でプログラムを記述するプログラミング言語です。C言語で記述されたプログラムをCPUに理解させるためには「コンパイラ」と呼ばれる変換プログラムを使って,C言語の表現を「マシン語(CPUが解釈・実行できる数値の羅列)」のプログラムにしなければなりません。Windows環境の場合,リスト1の内容をKasan.cというファイル名で保存し,それをコンパイラで変換すると,Kasan.exeというマシン語のファイルが生成されます(図2[拡大表示])。するとCPUは,Kasan.exeの内容を解釈・実行できるのです。

 数値の羅列であるマシン語でプログラムを記述できる人などいないでしょう。そこで,マシン語の数値が表す命令にニックネーム(英語を短縮したようなもの)を付け,ニックネームを使ってプログラミングする手法が考案されました。これを「アセンブリ言語」と呼びます。ニックネームのことを「ニーモニック」と呼びます。アセンブリ言語で記述されたプログラムは,ニーモニックを書き並べたものとなります。ニーモニックは,CPUのハードウエア的な動作を表すものです。

 アセンブリ言語で記述されたプログラムは,Kasan.asmのようなファイル名で保存されます。正確に言えば,ニーモニックで記述されたKasan.asmファイルをマシン語のKasan.exeファイルに変換するプログラムが「アセンブラ」です。ただし,アセンブリ言語のことをアセンブラと呼ぶ場合が多いので,この連載でも今後はアセンブラという言葉を使うことにします。

●アセンブラとマシン語は1対1に対応する

 リスト2は,アセンブラのプログラムとマシン語のプログラムの対応を示したものです。PUSHやMOVなどがニーモニックです。55や8B ECなどがマシン語です。このプログラムの機能は,前に示したC言語のプログラムと同じです。プログラムの内容を理解する必要はありません。雰囲気だけつかんでください。

 C言語のプログラムに比べて,アセンブラのプログラムは行数が多くなっていることが分かるでしょう。これは,C言語で使われる1つの命令がコンパイル後に複数のマシン語に変換されるのに対し,アセンブラで使われる1つの命令がアセンブル後に1つのマシン語に変換されるからです。アセンブラとマシン語は,1対1に対応します。したがって,アセンブラを使ってプログラミングすることは,マシン語を使ってプログラミングすることと同等です。だからこそ勉強になるのです。

リスト2●アセンブラとマシン語の対応

アセンブラマシン語
PUSHBP55
MOVBP,SP8B EC
SUBSP,483 EC 04
LEAAX,[BP-2]8D 46 FE
PUSHAX50
MOVAX,Z4B8 00 00
PUSHAX50
CALLscanf_E8 00 00
ADDSP,483 C4 04
LEAAX,[BP-4]8D 46 FC
PUSHAX50
MOVAX,Z5B8 04 00
PUSHAX50
CALLscanf_E8 00 00
ADDSP,483 C4 04
MOVAX,[BP-2].W8B 46 FE
ADDAX,[BP-4].W03 46 FC
PUSHAX50
MOVAX,Z6B8 08 00
PUSHAX50
CALLprintf_E8 00 00
ADDSP,483 C4 04
MOVSP,BP8B E5
POPBP5D
RETC3

●COMET IIとCASL II

 CPUの種類が異なれば,解釈・実行できるマシン語の種類も異なります。したがって,マシン語の数値に対応するニーモニックの種類も異なります。前に示したアセンブラのプログラムは,皆さんのパソコンで使われているPentiumなどの,俗に「x86系」と呼ばれるCPU用のものです。

図3●プログラマから見たハードウエアの構成要素

 x86系のCPUは機能が豊富であり,多くのニーモニックが用意されています。はじめてアセンブラを学ぶ人には,高機能過ぎて不向きでしょう。そこで,この連載では,COMET II(コメット・ツー)というハードウエアを対象としたCASL II(キャスル・ツー)と呼ばれるアセンブラを取り上げることにします。これらは,経済産業省が主管している国家認定試験である「情報処理技術者試験」の題材となっているものです。COMET IIは架空のハードウエアであり,CASL IIは架空のアセンブラです。COMET IIのハードウエア構成が単純であるためCASL IIで使われるニーモニックの数も少なく(第2回の連載で紹介しますが20数個です),だれでも簡単にマスターできます。はじめてアセンブラを学ぶ人に適しています。

 コンピュータのハードウエアの主要な構成要素は,CPU,メモリー,I/O(アイ・オー)の3つです。CPUは,プログラムを解釈・実行します。メモリーは,プログラム(命令とデータ)を記録します。I/Oは,コンピュータ本体と周辺装置(キーボード,ディスプレイ,ディスク装置など)を接続します。アセンブラで作成するプログラムの内容は,CPUがメモリーやI/Oとデータの入出力を行い,CPUの内部でデータの演算を行うものとなります。これが,ハードウエアを意識したプログラミングというものです(図3)。

●11個あるレジスタ

図4●COMET IIのCPUのレジスタ

 CPUの内部には「レジスタ」があります。レジスタは,命令やデータを格納する入れ物です。ただし,ただの入れ物ではなく,データを演算する機能も持っています。COMET IIのCPUの中には,十数個のレジスタがあり,名前(GR0やGR1など)で区別されます(図4[拡大表示])。アセンブラのプログラムでは,レジスタを名前で指定します。

 個々のレジスタの役割を説明しましょう。PCは,プログラムの流れを制御する「プログラム・カウンタ(Program Counter)」です。SPは,メモリー内の領域を利用するための「スタック・ポインタ(Stack Pointer)」です。GR0~GR7は,データの演算などに使われる「汎用レジスタ(General Register)」です。汎用レジスタの数が8個もあるのは,GR1で繰り返し回数をカウントしながらGR2で加算処理を行うような使い方をするからです。FRは,演算結果を記録する「フラグ・レジスタ(Flag Register)」です。PC,SP,GR0~GR7のサイズは,16ビットです。FRだけ,サイズが3ビットになっています。

図5●16ビットのレジスタのイメージ
図6●COMET IIのメモリー
図7●COMET IIのI/O入出力

 コンピュータの内部では,あらゆる情報を2進数の数値で取り扱っています。2進数とは,0と1だけを使って数を表す方法です。2進数の1けたのことを「ビット」と呼びます。したがって,16ビットのレジスタは,0と1のいずれかを格納した小さな箱を16個並べたものだと考えられます(図5[拡大表示])。

 COMET IIのメモリーは,命令またはデータを表す16ビットの入れ物が並んだものです。メモリーは,CPU内のレジスタとは異なり,演算機能を持たない単なる入れ物です。個々の入れ物は,番号で区別されます。この番号のことを「メモリー・アドレス」と呼びます。メモリー・アドレスの単位は「番地」です。COMET IIには,0番地~65535番地の範囲のメモリ・アドレスを持つメモリー(65536個の入れ物)があります。アセンブラのプログラムでは,メモリーの位置をメモリー・アドレスで指定します(図6[拡大表示])。

 COMET IIのI/Oは,プログラムから直接操作できないようになっています。キーボードからデータを入力したり,ディスプレイにデータを表示する場合には,架空のOS(このOSには名前が付けられていません)の機能を利用することになっています。アセンブラのプログラムからOSが提供する機能を呼び出すことで,間接的にI/Oとの入出力を行うのです。これを「スーパーバイザ・コール(またはシステム・コール)」と呼びます。スーパーバイザとは,OSのことです。皆さんのパソコンで動作している本物のプログラムでも,WindowsというOSの機能を利用して間接的にI/Oとの入出力を行っています。スーパーバイザ・コールに関しては,連載の第4回で詳しく説明します(図7[拡大表示])。

 今回は,ウォーミングアップとして,アセンブラの概要とこれから用いる架空のハードウエアCOMET IIのレジスタだけを説明しました。次回からは,CASL IIのニーモニックの種類を説明し,アセンブラのサンプル・プログラムを紹介して行きます。ただし,この連載の目的は,アセンブラを使いこなせるようになることではありません。アセンブラを学ぶことで,コンピュータとプログラムの本当の姿を知ることです。そのためには,架空のハードウエアCOMET IIと架空のアセンブラCASL IIで十分です。

【今後の予定】
第2回 命令の種類とプログラムの流れ
第3回 主プログラムと副プログラム
第4回 スーパーバイザ・コール
第5回 アセンブラでソートとサーチ