コンテンツにスキップ

英文维基 | 中文维基 | 日文维基 | 草榴社区

「アセンブリ言語」の版間の差分

出典: フリー百科事典『ウィキペディア(Wikipedia)』
削除された内容 追加された内容
Melan (会話 | 投稿記録)
(3人の利用者による、間の4版が非表示)
1行目: 1行目:
{{プログラミング言語}}
{{プログラミング言語}}
[[ファイル:Motorola 6800 Assembly Language.png|thumb|[[モトローラ]] [[MC6800]] のアセンブリ言語のソースコード]]
'''アセンブリ言語'''(アセンブリげんご、assembly language)とは、[[コンピュータ]]を動作させるための[[機械語]]を人間にわかりやすい形で記述する、代表的な[[低級言語]]である。
'''アセンブリ言語'''(アセンブリげんご、assembly language)とは、[[コンピュータ]]、[[マイクロコントローラ]]、その他のプログラム可能な機器を動作させるための[[機械語]]を人間にわかりやすい形で記述する、代表的な[[低水準言語]]である。


== 概要 ==
== 概要 ==
[[CPU]]が直接実行できる言語は機械語のみであるが、機械語は数字内部的には[[二進]])の羅列なので人間には理解しにくい。そこで、機械語を直接記述するのではなく、ニーモニックと呼ばれる命令語で[[プログラム (コンピュータ)|プログラム]]を記述することで、人間により分かりやすくしたものがアセンブリ言語である。アセンブリ言語の文法はCPUの[[コンピュータ・アーキテクチャ|アーキテクチャ]]に依存するため、[[高言語]]のような[[移植性]]はない。
[[プロセッサ]]が直接実行できる言語は機械語のみであるが、機械語はバイナリ(数)の羅列なので人間には理解しにくい。そこで、機械語を直接記述するのではなく、ニーモニックと呼ばれる命令語で[[プログラム (コンピュータ)|プログラム]]を記述することで、人間により分かりやすくしたものがアセンブリ言語である。アセンブリ言語の[[プログラム意味論|意味]]は個々のプロセッサに依存するため、[[高水準言語]]のような[[移植性]]はない。


アセンブリ言語を機械語に変換する事を'''アセンブル''' (assemble) すると言い、それを行うプログラムの事を'''アセンブラ''' (assembler) と言う。なお、アセンブリ言語の意味で「アセンブラ」または「アセンブラ言語」(Assembler Language)と呼ぶ場合も多い<ref>IBMは[[System/360]]から2011年現在まで一貫してアセンブラ言語(Assembler Language)と呼んでいる。例:[http://www-01.ibm.com/software/awdtools/hlasm/ IBM High Level Assembler]</ref>。
アセンブリ言語で書かれたプログラムを機械語プログラムに変換する事を'''アセンブル''' (assemble) すると言い、それを行うプログラムの事を'''アセンブラ''' (assembler) と言う。なお、アセンブリ言語の意味で「アセンブラ」または「アセンブラ言語」(Assembler Language)と呼ぶ場合も多い<ref group="注">IBMは[[System/360]]から2011年現在まで一貫してアセンブラ言語(Assembler Language)と呼んでいる。例:[http://www-01.ibm.com/software/awdtools/hlasm/ IBM High Level Assembler]</ref><ref>Stroustrup, Bjarne, ''The C++ Programming Language'', Addison-Wesley, 1986, ISBN 0-201-12078-X: ''"C++ was primarily designed so that the author and his friends would not have to program in assembler, C, or various modern high-level languages."'' - ''assembler'' を ''assembly language'' の意味で使っている例</ref>。


初期のコンピュータでは「アセンブラ」を「アセンブリプログラム」と呼ぶ例もあった<ref>Saxon, James, and Plette, William, ''Programming the IBM 1401'', Prentice-Hall, 1962, LoC 62-20615. - ''assembly program'' という用語を使っている例</ref>。
アセンブリ言語の命令は、アセンブラに対する命令(疑似命令)や[[マクロ (コンピュータ用語)|マクロ]]命令を除き、機械語と1対1で対応し、[[プログラマ]]がCPUの動作を把握しながらプログラムを記述する事ができる。そのため、

* 実行速度やプログラムサイズに制限があるアプリケーションで、高級言語である[[コンパイラ最適化|コンパイラの最適化]]能力では達成できない[[最適化 (情報工学)|最適化]]を手作業で行いたい場合
アセンブリ言語の命令は、アセンブラに対する命令(疑似命令)や[[マクロ (コンピュータ用語)|マクロ]]命令を除き、基本的には<ref group="注">MIPSのアセンブラの一部など、命令の遅延分岐スロットへの移動を勝手に行うものもある。OPTASM(SLR社)という最適化アセンブラもあった。</ref>機械語と1対1で対応し、[[プログラマ]]がCPUの動作を把握しながらプログラムを記述する事ができる。
* CPUの動作をプログラマが完全に制御する必要がある場合

* メモリ容量や演算実行速度などの[[計算資源|リソース]]に厳しい制約がある用途
アセンブリ言語ではマシンの低水準な操作または'''オペコード'''を'''ニーモニック'''で表す。オペコードによっては、機械語命令の一部として1つまたは複数の'''オペランド'''が必要である。また、多くのアセンブリ言語はオペランドとしてラベルやシンボルを使ってアドレスや定数を表すことができ、それらの値をプログラム内にそのまま書く(ハードコーディング)のを防ぐことができる。'''マクロアセンブラ'''は[[マクロ (コンピュータ用語)|マクロ命令]]機能を備えており、アセンブリ言語のテキストに名前を事前に割り当て、その名前を使うことで他のコードにそのテキストを挿入できる。多くのアセンブラは、プログラム開発を支援したり、アセンブリ過程を制御したり、[[デバッグ]]を支援したりといった付加機構を備えている。
などにはアセンブリ言語によるプログラムが行われる。現在でも、例えば[[オペレーティングシステム|OS]][[カーネル]]や[[デバイスドライバ]]、[[組み込みシステム]]の開発といった場面で頻繁に用いられる。


== 歴史 ==
== 歴史 ==
18行目: 19行目:
そこで、機械語そのものを書く代わりに機械語の「意味」に相当する短い記号や単語を対応させ、それを記述してプログラミングをすることが考えられた。
そこで、機械語そのものを書く代わりに機械語の「意味」に相当する短い記号や単語を対応させ、それを記述してプログラミングをすることが考えられた。


世界で最初に実用的に稼働した[[ノイマン型]]電子計算機とされる[[EDSAC]]のローダ(外部記憶装置からプログラムやデータを読み出して主記憶装置に書き込むプログラム)において、既に原始的なアセンブラの機能が実装されている。EDSACはワード指向アーキテクチャで命令長が1ワードの固定長命令のマシンであり、入力装置は紙テープでありキャラクタ指向である。紙テープ上の A 1 0 0 F という文字列から十進法を数値に変換するなどの処理をおこない、「100番地の値を[[アキュムレータ (コンピュータ)|アキュムレータ]]に加算する」という1ワードの命令を生成する、といった機能が、EDSACのローダには実装されていた。
例えば[[x86]] CPUの機械語
{{indent|10110000 01100001<sub>2</sub> (B0 61<sub>16</sub>)}}
は「AL[[レジスタ (コンピュータ)|レジスタ]]に61<sub>16</sub> (97) という数値を格納せよ」という意味であるが、この数列から意味を読み取るのは難しいので、
<source lang="asm">
MOV AL, 61H
</source>
と書いておく([[Microsoft Macro Assembler|MASM]]での例)。ちなみに、"MOV" は 英単語 "move"(動かす)の略である。


機械語への変換は人間が手で行うこともあり、'''ハンド・アセンブル'''と呼ぶ。単に定められた規則に従って記号や単語から機械語を生成するだけなので、自動的に機械語を出力するプログラムが作られるようになった。このプログラムを'''アセンブラ'''という。
このように、機械語そのものよりも親しみやすい記法でプログラムを書いておいて、プログラムが完成したときにまとめて機械語に変換するのである。


コンピュータの歴史の初期には、このような、プログラムによって機械語プログラムを生成することを[[自動プログラミング]]と呼んだ。
当初、この機械語への変換は人間が手で行っていた。これを'''ハンド・アセンブル'''と呼ぶ。
しかし、この変換は単に定められた規則に従って記号や単語から機械語を生成するだけなので、この作業をコンピュータに行わせることが考えられた。
そしてアセンブリ言語を与えると、自動的に機械語を出力するプログラムが作られるようになった。このプログラムを'''アセンブラ'''という。アセンブラの登場当初は、アセンブラで機械語のプログラムを生成することを[[自動プログラミング]]と呼んだ。


[[ドナルド・ギリース]]には、まだ発明されていなかったアセンブラを開発中に、[[フォン・ノイマン]]に開発を即座に止めるように言われたという、1950年代初期ならではの逸話がある。というのも、当時は人間が手作業でもできるような瑣末な仕事をコンピュータにさせるような時代が来るとは考えられておらず、単に時間の無駄だと考えられたのである。
[[ドナルド・ギリース]]には、まだ発明されていなかったアセンブラを開発中に、[[フォン・ノイマン]]に開発を即座に止めるように言われたという、1950年代初期ならではの逸話がある。というのも、当時は人間が手作業でもできるような瑣末な仕事をコンピュータにさせるような時代が来るとは考えられておらず、単に時間の無駄だと考えられた(ノイマンには<ref group="注">前述したように、1950年にはEDSACにおいて原始的なアセンブラが存在していた。時代背景というよりは、ノイマンや、チューリングにもこういったこぼれ話はあるが、そういった天才でも未来を全て知っているわけではない、という教訓であろう。</ref>)のである。


== 文法 ==
== 主要概念 ==
=== アセンブラ ===
アセンブリ言語によるプログラミングは、基本的に機械語の命令列を記述することでおこなう。
'''アセンブラ'''は、アセンブリ命令ニーモニックを[[オペコード]]に変換し、[[識別子|シンボル名]]をメモリ位置や他の実体に変換することで[[オブジェクトコード]]を生成する<ref name="Salomon">David Salomon (1993). ''[http://www.davidsalomon.name/assem.advertis/asl.pdf Assemblers and Loaders]''</ref>。シンボル名による参照の利用はアセンブラの重要な機能であり、面倒な計算やプログラム修正に伴うアドレスの更新の手間を省くことができる。多くのアセンブラは[[マクロ (コンピュータ用語)|マクロ]]機能を備えており、よく使用する命令列を[[サブルーチン]]呼び出しではなく[[インライン展開]]することができる。


==== パス回数 ====
機械語の命令(インストラクション)は、アセンブリ言語においては普通、ニーモニックと呼ばれる、機械語の命令がプロセッサでおこなう動作を表現する英単語ないしその省略表現(LoadをLDなど)で表現する。機械語の命令セットは、プロセッサによって異なる。一般にプロセッサの設計者あるいは製造者によって定義されたニーモニックが標準とされるが、アセンブラによってはこれと異なるニーモニックを用いる場合もある([[GNU]]アセンブラのgasの[[インテル]]プロセッサ用など)。
実行ファイルを生成するのにソースファイルを何回パス(走査)するかでアセンブラを分類できる。
; ワンパスアセンブラ
: ソースコードを1回だけパスするアセンブラ。定義される前にシンボルが使われているとオブジェクトコードの最後に "errata" を置く必要があり、[[リンケージエディタ|リンカ]]または[[ローダ]]が未定義シンボルが使われていた位置にあるプレースホルダーを書き換える。あるいは、未定義なシンボルを使用するとエラーになる。
; マルチパスアセンブラ
: 最初のパスで全シンボルとその値の表を作成し、その表を使ってその後のパスでコードを生成する。
どちらの場合も、アセンブラは最初のパスで各命令のサイズを確定させる必要があり、それによって後に出現するシンボルのアドレスを計算する。命令のサイズは後から定義されるオペランドの型や距離に依存することがあるため、アセンブラは最初のパスでは悲観的な見積もりをし、必要に応じてその後のパスまたは errata にて1つ以上の[[NOP]]命令(何もしない命令)を挿入してすき間を生める必要がある。最適化を行うアセンブラでは、最初の悲観的コードをその後のパスで稠密なコードに書き換えてアドレスの再計算を行うことがある。


もともとワンパスアセンブラは高速であるためよく使われていた。マルチパス動作をするには、[[磁気テープ]]を巻き戻したり[[パンチカード]]のデッキをセットし直して読み込む必要があったためである。現代のコンピュータではマルチパスであってもそのような遅延は生じない。マルチパスアセンブラは errata がないため、[[リンケージエディタ|リンク処理]](アセンブラが直接実行コードを生成する場合は[[ローダ]]の処理)が高速化される<ref>{{Cite book|last=Beck|first=Leland L.|title=System Software: An Introduction to Systems Programming|publisher=Addison Wesley|year=1996|chapter=2}}</ref>。
アセンブリ言語プログラムのソースコードには、機械語に対応したニーモニックの他に、機械語には変換されない、アセンブラに対する指示文が含まれる。これを'''疑似命令'''または'''アセンブラ命令'''といい、ラベルの宣言、セクションの定義、条件アセンブルや繰り返しブロック、マクロなどが含まれる。'''マクロ'''は、複数のニーモニックを1つの命令文で記述する構文で、マクロを使えるアセンブラをマクロアセンブラという。


==== 高水準アセンブラ ====
また、RISCアーキテクチャ向けのアセンブリ言語では、その命令セットに対応するもの以外のニーモニック(例えば定型的に用いられる複数の命令の組み合わせ)が標準で定義されていて、そのニーモニックを記述することで、動作が同じ命令に変換されたり、複数の命令を組み合わせた形にアセンブルされる。
より洗練された{{仮リンク|高水準アセンブラ|en|high-level assembler}}は言語として次のような抽象化を提供する。
* 高度な[[制御構造]]
* 高水準なプロシージャ/関数の宣言と呼び出し
* 構造体/レコード、共用体、クラス、集合といった高水準な抽象[[データ型]]
* 洗練されたマクロ処理(なお、マクロ機能は1950年代末の [[IBM 700/7000 series|IBM 700 シリーズ]]や1960年代の[[System/360]]などで普通に使われていた)
* [[クラス (コンピュータ)|クラス]]、[[オブジェクト (プログラミング)|オブジェクト]]、[[抽象化 (計算機科学)|抽象化]]、[[ポリモーフィズム]]、[[継承 (プログラミング)|継承]]といった[[オブジェクト指向]]の特徴を備えたアセンブラ<ref>Hyde, Randall. "Chapter 12 – Classes and Objects". The Art of Assembly Language, 2nd Edition. No Starch Press. © 2010.</ref>


==== クロスアセンブラとメタアセンブラ ====
なかには、[[パイプライン処理]]などを最適化するために命令順序を入れ替えたり、ラベルの位置関係によってアドレッシングモードを最適化するアセンブラもあり、必ずしもソーステキストの記述とアセンブルの結果が直接対応するとは限らない。
'''クロスアセンブラ'''は[[クロスコンパイラ]]と似ており、あるプラットフォームで動作するが、そのプラットフォームではなく別のプラットフォーム向けのオブジェクトコードを生成するアセンブラを指す。小型の組み込みシステムなど、対象システムでアセンブラを動作させられない場合に使用することが多い。その場合、生成した[[機械語]]コードを対象システムに転送する何らかの手段が必要である。単に機械語コードをバイト単位に転送することもできるが、[[ASCII]]表現の転送用フォーマットがメーカーから提供されている(モトローラの[[:en:SREC (file format)|SREC]]、インテルの[[:en:Intel HEX|HEX]]など)。


'''メタアセンブラ'''は、アセンブリ言語の文法や意味論を記述したものを入力とし、その言語のためのアセンブラを出力するプログラムである<ref>[http://www.encyclopedia.com/doc/1O11-metaassembler.html (John Daintith, ed.) A Dictionary of Computing: "meta-assembler"]</ref>。
機械語のコードは、処理の内容を指示する'''オペコード'''と、処理の対象を指示する'''オペランド'''から成る。それに従い、アセンブリ言語のソースコードでは、オペコードに対応するニーモニックと、オペランドを組み合わせて記述する。

=== アセンブリ言語 ===
アセンブリ言語で書かれたプログラムは、プロセッサの命令に対応したニーモニックの列、ディレクティブや擬似命令と呼ばれるメタな文、コメント、データで構成されている。ニーモニックとは、機械語の命令がプロセッサでおこなう動作を表現する英単語ないしその省略(LoadをLDなど)で表現したものである。通常の文はオペコードのニーモニックで始まり、パラメータ(データ、引数)のリストがそれに続く<ref name="intel-1999">{{Cite book |title=Intel Architecture Software Developer’s Manual, Volume 2: Instruction Set Reference |year=1999 |publisher=INTEL CORPORATION |url= http://download.intel.com/design/PentiumII/manuals/24319102.PDF |accessdate=2010-11-18}}</ref>。それらをアセンブラが[[機械語]]命令に翻訳し、メモリにロードして実行できる形式にする。

なかには、[[パイプライン処理]]などを最適化するために命令順序を入れ替えたり、ラベルの位置関係によってアドレッシングモードを最適化するアセンブラもあり、必ずしもソーステキストの記述とアセンブルの結果が直接対応するとは限らない。


オペランドにはソースとデスティネーションの二種類があり、データとして読み取られるのがソースで、オペコードで示された命令の実行結果が格納されるのがデスティネーションである。ソースには定数・レジスタ・メモリのいずれか、デスティネーションにはレジスタ・メモリのいずれかを指定する。
オペランドにはソースとデスティネーションの二種類があり、データとして読み取られるのがソースで、オペコードで示された命令の実行結果が格納されるのがデスティネーションである。ソースには定数・レジスタ・メモリのいずれか、デスティネーションにはレジスタ・メモリのいずれかを指定する。


なお、オペランドの記述順序は、上の例では「デスティネーション, ソース」だが、「ソース, デスティネーション」の順に書くアセンブリ言語もある。また、オペランドの個数は命令によって異なり、典型的なオペランドは0以上の'''ソース'''と1つの'''デスティネーション'''からなるが、プロセッサにより、暗黙のソースやデスティネーションを持つためにそれらを記述しない命令や、オペランドを持たない命令を持つ場合もある。
たとえば先述の、

例えば、次の命令は[[x86]]/[[IA-32]]プロセッサのもので、[[定数 (プログラミング)|8ビット即値]]を[[レジスタ (コンピュータ)|レジスタ]]に入れる命令である。この命令のバイナリコードは 10110 で、その後に3ビットのレジスタを指定する識別子が続く。''AL'' レジスタの識別子は 000 なので、次に示す[[機械語]]は ''AL'' レジスタに 01100001 というデータをロードする<ref name="intel-1999-MOV">{{Cite book |title=Intel Architecture Software Developer’s Manual, Volume 2: Instruction Set Reference |year=1999 |publisher=INTEL CORPORATION |pages=442 and 35 |url= http://download.intel.com/design/PentiumII/manuals/24319102.PDF |accessdate= 2010-11-18}}</ref>。
10110000 01100001
このバイナリコードを人間が読みやすいように[[十六進法]]で表現すると次のようになる。
B0 61
ここで、<code>B0</code> は「''AL''に後続の値をコピーする」ことを意味し、<code>61</code> は 01100001 を十六進法で表したもの([[十進法]]では 97)である。インテルのアセンブリ言語では、この種の命令に MOV というニーモニックを割り当てており、セミコロン以下に説明的コメントを添えたアセンブリ言語での表現は次のようになる。
<source lang="asm">MOV AL, 61h ; Load AL with 97 decimal (61 hex)</source>
この場合、定数61Hがソース、レジスタALがデスティネーションに該当し、命令が実行されると、定数61Hが、レジスタALに単純に格納される。これが人間にとってはさらに読みやすく覚えやすい。

アセンブリ言語によっては、MOV のようなニーモニックはロードやデータのコピー/移動を行う命令群を表すのに使われ、オペランドの種類によって実際のオペコードが異なっていてもニーモニックとしては同じものを使う。また、データのコピー/移動の方向などによって別々のニーモニックを使うアセンブリ言語もある(「メモリからレジスタへの移動」を L、「レジスタからメモリへの移動」を ST、「レジスタからレジスタへの移動」を LR、「即値をメモリへ移動」を MVI など)。

インテルのオペコード 10110000 (<code>B0</code>) は8ビットの値を ''AL'' レジスタにコピーするが、10110001 (<code>B1</code>) は ''CL'' レジスタにコピーし、10110010 (<code>B2</code>) は ''DL'' レジスタにコピーする。これらをアセンブリ言語で表現すると次のようになる<ref name="intel-1999-MOV"/>。
<source lang="asm">
MOV AL, 1h ; Load AL with immediate value 1
MOV CL, 2h ; Load CL with immediate value 2
MOV DL, 3h ; Load DL with immediate value 3
</source>
MOVの構文には次の例のようにさらに複雑なものもある<ref>{{Cite web |last=Evans |first=David |title=x86 Assembly Guide |url= http://www.cs.virginia.edu/~evans/cs216/guides/x86.html |publisher=University of Virginia |accessdate= 2010-11-18|year=2006}}</ref>。
<source lang="asm">
<source lang="asm">
MOV EAX, [EBX] ; Move the 4 bytes in memory at the address contained in EBX into EAX
MOV AL, 61H
MOV [ESI+EAX], CL ; Move the contents of CL into the byte at address ESI+EAX
</source>
</source>
MOV というニーモニックを使った文は、その内容によってアセンブラが 88-8E、A0-A3、B0-B8、C6、C7 のいずれかのオペコードに変換するので、プログラマはオペコードを知る必要がないし、オペコードを覚える必要もない<ref name="intel-1999-MOV"/>。
は、ニーモニック「MOV」と、2つのオペランド「AL」と「61H」からなり、
{{indent|10110000 01100001<sub>2</sub> (B0 61<sub>16</sub>)}}
と変換される。この場合、定数61Hがソース、レジスタALがデスティネーションに該当し、命令が実行されると、定数61Hが、レジスタALに単純に格納される。


アセンブリ言語から機械語への変換はアセンブラが行うが、逆方向の変換の一部は[[逆アセンブラ]]が行う。[[高水準言語]]とは異なり、単純なアセンブリ構文と機械語命令には[[全単射|1対1の関係]]がある。しかしアセンブラは擬似命令(マクロの一種)を提供していることがあり、1つの擬似命令をよく使われる機械語命令列に展開する。例えば、大小比較による条件分岐命令を持たないマシンの場合、アセンブラで大小比較命令とゼロなら分岐する条件分岐命令(比較命令の結果を使用)に展開される擬似命令を用意したりする。多くの高機能アセンブラは豊富な[[マクロ (コンピュータ用語)|マクロ]]言語機能を備えており、複雑なコード列やデータシーケンスを生成できる。
なお、オペランドの記述順序は、上の例では「デスティネーション, ソース」だが、「ソース, デスティネーション」の順に書くアセンブリ言語もある。また、オペランドの個数は命令によって異なり、典型的なオペランドは0以上の'''ソース'''と1つの'''デスティネーション'''からなるが、プロセッサにより、暗黙のソースやデスティネーションを持つためにそれらを記述しない命令や、オペランドを持たない命令を持つ場合もある。


[[コンピュータ・アーキテクチャ]]はそれぞれ独自の機械語を持つ。アーキテクチャが異なれば、サポートする命令の数や種類が異なり、レジスタの大きさや個数が異なり、データの格納形式が異なる。汎用コンピュータの多くは機能的にほぼ同等だが、実装は異なるので、アセンブリ言語にはその差異が反映されている。
<!-- 下記は、アセンブリ言語、というよりは、ISA(命令セット)の説明です。
多くのCPUでは、オペコードとオペランドが頻繁に使われる組み合わせなら、機械語の1ワードの中にまとめて収めることができる。先述の例
: MOV AL, 61H
: 10110000 01100001<sub>2</sub> (B0 61<sub>16</sub>)
では、オペコードMOVとオペランドALが、B0<sub>16</sub>という1ワード(この例では8ビット)に収められている。こうすることで、メモリを節約し、また時間のかかるメモリアクセス時間を短縮している。アーキテクチャとして先発である[[CISC]]アーキテクチャの[[命令セット]]はこの傾向が強いが、[[RISC]]アーキテクチャも後に、組み込み用途において短い命令を求められたため、短い命令を備えているものがある。
-->


機械語の[[命令セット]]は、プロセッサによって異なる。[[命令セット]]が同じでも様々なニーモニックやアセンブリ言語の文法が存在しうる。一般にプロセッサの設計者あるいは製造者によって定義されたニーモニックが標準とされるが、アセンブラによってはこれと異なるニーモニックを用いる場合もある([[GNU]]アセンブラのgasの[[インテル]]プロセッサ用など)。
== アセンブラとコンパイラ ==
<!--組み込みシステムやIBM系汎用機の開発現場では稀ではありません。
現在アセンブリ言語を直接人間が記述することは稀だが、-->多くのコンパイラは、いったんコードをアセンブリ言語で出力してからアセンブラに通す。その意味ではアセンブリ言語は、目に見えない形ではあるが最も利用頻度の高いプログラミング言語といえる。


== 言語設計 ==
一部の高級言語のコンパイラでは、[[インラインアセンブラ]]を使うことで、高級言語のソースの中にアセンブリ言語による記述を含めることができる。最小限のアセンブリ言語の知識で書くことができ、プログラムで実行時間の多くを占める部分をインラインアセンブラによる記述に置き換えることで、全体をアセンブリ言語で書いたプログラムに近い実行速度を実現できることもあるが、特定のCPUのアーキテクチャに依存する記述となるので互換性や移植性は大きく損なわれる。
=== 基本要素 ===
アセンブラの開発者によって用語の使い方に大きな差異があり、文の分類などが異なる。例えば、マシンのニーモニックや拡張ニーモニック以外は全て擬似命令と呼ぶ場合もある。典型的なアセンブリ言語は、プログラムの操作の定義に使われる命令文を以下の3種類に分類する。
* オペコードのニーモニック
* データセクション
* アセンブリディレクティブ


==== オペコードのニーモニックと拡張ニーモニック ====
分割コンパイルで作成するプログラムの一部のモジュールをアセンブリ言語で書くこともある。この場合、コンパイラの[[呼出規約]]にしたがってアセンブリ言語の[[プロシージャ]]を書き、コンパイラが生成した[[オブジェクトファイル|オブジェクト]]や[[ライブラリ]]と、アセンブラが生成したそれらを、対応した[[リンケージエディタ|リンカ]]で結合する。
アセンブリ言語の命令文は一般に非常に単純で、[[高水準言語]]のそれとは異なる。一般にニーモニックは1つの機械語命令(オペコード)のシンボル名であり、個々の機械語命令には少なくとも1つのオペコード・ニーモニックが対応している。命令は一般に「オペコード」と0以上の「オペランド」で構成される。多くの命令は1つまたは2つの値を参照する。オペランドには即値(命令内に置かれる値)、レジスタ(暗黙のうちに使用される場合もある)、記憶装置内のデータの位置を示すアドレスなどがある。「拡張ニーモニック」はオペコードと特定オペランドの組合せを表すのに使われることが多い。例えばSystem/360では、'''BC''' 命令にマスク15を組み合わせたものが '''B'''、'''BC''' 命令にマスク0を組み合わせたものが '''NOP''' という拡張ニーモニックで表される。


「拡張ニーモニック」は命令の特殊な用途をサポートするのに使われることが多く、本来の命令の名称からはその用途が連想できないときに使うことが多い。例えば、多くのCPUは明示的に[[NOP]]命令を用意していないが、その用途に使える命令は存在する。8086では ''xchg ax,ax'' という命令が ''nop'' として使えるので、アセンブリ言語で ''nop'' を記述すると ''xchg ax,ax'' という命令に変換される。逆アセンブラにもこのあたりを認識し、''xchg ax,ax'' を ''nop'' に変換するものがある。同様にIBMの[[System/360]]と[[System/370]]のアセンブラでは、拡張ニーモニック ''NOP'' と ''NOPR'' を使用し、それぞれ ''BC'' と ''BCR'' のマスク0の命令に変換する。[[SPARC]]アーキテクチャでは、拡張ニーモニックを ''synthetic instructions'' と呼んでいる<ref>{{Cite web |url= http://www.sparc.com/standards/V8.pdf |publisher=SPARC, International |title=The SPARC Architecture Manual, Version 8 |year=1992 |accessdate=2012-10-27}}</ref>。
== 主なアセンブラ ==
* [[IBM High Level Assembler|IBM High Level Assembler (HLASM)]] - [[IBM]]系[[メインフレーム]]用のアセンブラ。
* [[PDP-8#プログラム例|PDP-8のアセンブリ言語]] - PAL-III(Program Assembly Language III)
* [[CAP-X]] - CASL 以前に情報処理技術者試験で使われていたアセンブリ言語
* [[CASL]] - [[情報処理技術者試験]]用に作られたアセンブリ言語。同時に定義されているペーパーマシンCOMET用
* [[:en:As (Unix)|as]] - [[UNIX]]用のアセンブラ
* [[GNUアセンブラ|GNUアセンブラ (gas)]] - [[GNU]]が開発する、[[80x86|x86]]、[[MC68000|680x0]]、[[SPARC]]、[[VAX]]などの各種CPU用のアセンブラ
* [[Microsoft Macro Assembler|Microsoft Macro Assembler (MASM)]] - [[インテル]]のx86 CPU用に[[マイクロソフト]]が開発したアセンブラ
* [[Netwide Assembler|Netwide Assembler (nasm)]] - MASMと互換性の高いx86 CPU用アセンブラ
* [[Turbo Assembler|Turbo Assembler (TASM)]] - [[ボーランド]]が開発していた、MASMと互換性の高いx86 CPU用アセンブラ


アセンブラによっては単純な組み込みマクロ命令を備えており、数個の機械語命令に展開される。例えば一部の[[Z80]]用アセンブラでは、''ld hl,bc'' というマクロ命令を ''ld l,c'' と ''ld h,b'' という2命令に展開する<ref>http://www.z80.de/z80/z80code.htm</ref>。
== 亜種 ==

表記をニモニックやオペランド等のトークンの並びにする形式の他に、等号や記号を使ってより直感的に扱える物もある。
==== データセクション ====
* [[BASE-80|BASE, BASE-80]] Z80用アセンブラ
データと変数を保持するデータ要素を定義するのに使われる命令文がある。データの型、長さ、境界(アライメント)を定義する。また、そのデータがプログラム外部(別ファイルでアセンブルされたプログラム)からも利用可能なのか、それともデータセクションを定義したプログラム内でのみ使用可能なのかも定義できる。一部のアセンブラはこれを擬似命令に分類している。
* [[BASE-09]] MC6809用アセンブラ

BASEの表記例は下記の通り(BASE-09)
==== アセンブリディレクティブ ====
アセンブリディレクティブは擬似命令とも呼ばれ、アセンブラがアセンブリ実施中に実行すべき命令となっている<ref name="Salomon"/>。プログラマが入力するパラメータによって異なった形でアセンブルが行われるよう指示することができる。また、プログラムの見た目を操作して、[[可読性]]と保守性を向上させるのにも使われる。例えば、記憶装置の領域を予約し、その初期内容を指定するディレクティブなどがある。ディレクティブの名称はドットで始まることが多く、それによって通常のニーモニックと区別している。

擬似オペコード (pseudo-opcode) と言った場合、オブジェクトコードを実際に生成するディレクティブのみを指すこともある<ref>{{Cite web |last=Microsoft Corporation|title=MASM: Directives & Pseudo-Opcodes |url= http://flint.cs.yale.edu/cs422/doc/art-of-asm/pdf/CH08.PDF |accessdate=2011-03-19}}</ref>。

==== ラベル/シンボル ====
シンボリックアセンブラでは、任意の名前([[ラベル (プログラミング)|ラベル]]またはシンボル)とメモリ位置を対応付けることができる。通常、定数や変数に名前をつけることができ、命令文ではそれらの位置を名前で参照できる。実行コードではサブルーチンのエントリポイントと名前を関連付け、サブルーチンを名前で呼び出すことができる。サブルーチン内では、分岐命令の分岐先をラベルで示すことができる。一部のアセンブラは「ローカルシンボル」をサポートしており、通常のシンボルとは語彙的に区別する(例えば、"10$" を分岐先に使用するなど)。

一部のアセンブラは柔軟なシンボル管理を提供しており、複数の[[名前空間]]を管理したり、[[データ構造]]内のオフセットを自動的に計算したり、リテラル値やアセンブラが実施した単純な計算結果を参照するラベルを割り当てたりすることができる。ラベルは定数や変数を[[リロケータブル]]なアドレスで初期化するのにも使える。

==== コメント ====
他の言語と同様アセンブリ言語でも[[ソースコード]]にコメントを付与でき、アセンブラはそれらを無視できる。高水準言語に比べて可読性が低いため、コメントの重要性は高い。

これらの機能を多用することで低水準のコードのコーディングや保守の問題を大幅に単純化することができる。コンパイラや逆アセンブラが生成するアセンブリソースはコメントがなく、自動生成されるシンボルが意味不明で、データ定義もないため、非常に可読性が低い。

=== マクロ ===
多くのアセンブラは事前定義されたマクロをサポートしており、中にはユーザーが定義可能なマクロをサポートしているものもある。マクロは命令列と変数や定数の定義を埋め込むことができ、その中にオペコードやディレクティブの列が含まれる。マクロが定義されると、その名前をニーモニックとして使用できる。アセンブラはソース内にマクロを発見すると、対応するコード列に置き換え、元からソースにそのコード列が存在したかのように処理をする(アセンブラによっては、マクロを展開した中にマクロがあれば、それも展開することができる)。

なお、このような「マクロ」の定義は、例えば[[C言語]]でのマクロとは若干異なる。C言語のマクロは一般に #define というディレクティブで定義され、1行または多くても数行で済ませることが多い。アセンブラのマクロはそれ自体が長い「プログラム」であり、アセンブラがアセンブル時に解釈して実行する。

マクロは短い名前だが、数行からかなり長い行数のコードに展開されるので、アセンブリ言語のプログラムの見た目を短くすることができる。また、マクロによってアセンブリ言語プログラムに高水準の構造を追加でき、パラメータ付きのデバッグ用コードを埋め込むなどの利用法がある。

マクロアセンブラでは、マクロに[[引数|パラメータ]]を付与できる。中には洗練されたマクロ言語を備えたアセンブラもあり、オプションパラメータ、記号変数、条件文、文字列操作、算術演算などの高水準言語要素を持ち、マクロ実行中にそれらを使用でき、またマクロがコンテキストをセーブしたり情報を交換したりすることも可能である。したがってマクロの引数に基づいて大量のアセンブリ言語命令またはデータ定義を生成できる。例えば、レコード風のデータ構造や展開されたループを生成するのに使え、複雑なパラメータに基づいてアルゴリズム全体を生成することもできる。そのようなマクロで大いに拡張されたアセンブリ言語を使用すると、コンピュータの低水準の概念要素を扱う必要がなくなり、一種の高水準言語をつかっているのと同じことになる。

メインフレームの時代には、マクロは特定顧客の大規模ソフトウェアシステムのカスタマイズや、メーカーのオペレーティングシステムを顧客の要望に合わせた特注版にするのに使われていた。例えば、[[IBM]]の [[:en:VM (operating system)|VM/CMS]]、リアルタイムトランザクション処理用アドオン、[[CICS]]、{{仮リンク|IBM Airline Control Program|en|IBM Airline Control Program|label=ACP}}/[[Transaction Processing Facility|TPF]]([[CRS (航空)|コンピュータ予約システム]] (CRS) やクレジットカード会社で使われているトランザクションOS)などで使われてきた。

アセンブラのマクロ機能だけを全く異なる言語のコード生成に使うこともできる。例えば、[[COBOL]]のプログラムをマクロアセンブラのアセンブル時に実行されるオペレータで生成することができる。

というのも、1960年代に実用化された「マクロ処理」は「アセンブリ」とは独立した概念であり、マクロ処理は単なるオブジェクトコード生成というよりも現代的にはワードプロセッシングやテキストプロセッシングに近い。C言語にもマクロ処理の概念が導入されており、[[プリプロセッサ]]と呼ばれる。ただし、アセンブラのマクロプロセッサは[[チューリング完全]]だったが、C言語のプリプロセッサはそうではない(Cのプリプロセッサにはループ機能や "goto" 機能がない)。

マクロ処理の能力は大きいが、アセンブラ以外の高水準言語ではあまり使われなくなった(例外としてC/C++と[[PL/I]]がある)。

マクロのパラメータ置換は厳密に名前によってなされる。マクロ処理の際、パラメータ値がその名前を逐語的に置換する。そのため、パラメータとして式を指定したときよくあるバグが生じる。例えば次のようなマクロがあるとする。

foo: macro a
load a*b

このマクロは呼び出し側が変数名を指定し、広域変数または定数である b とその変数をかけることを想定している。しかし、foo のパラメータとして <tt>a-c</tt> を指定するとマクロは <tt>load a-c*b</tt> と展開されてしまう。これを防ぐにはマクロ定義内でパラメータを常に括弧で囲むか、呼び出し時にパラメータを括弧付きにするしかない<ref>{{Cite web |url= http://msdn.microsoft.com/en-us/library/503x3e3s%28v=VS.90%29.aspx |title=Macros (C/C++), MSDN Library for Visual Studio 2008 |publisher=Microsoft Corp. |accessdate=2010-06-22}}</ref>。

=== 構造化プログラミングサポート ===
[[構造化プログラミング]]の要素を取り入れたアセンブラもある。最初期の例として "Concept-14 macro set" がある。Dr. H.D. Mills (March, 1970) が提案し、IBMの連邦政府システム部門の Marvin Kessler が実装したもので、System/360 のマクロアセンブラに IF/ELSE/ENDIF などの制御構造を導入した<ref>{{Cite web |url= http://skycoast.us/pscott/software/mvs/concept14.html |title=Concept 14 Macros |publisher=MVS Software |accessdate=2009-05-25}}</ref>。これはアセンブリコードから[[Goto文|GOTO]]操作を削減または排除するもので、本質的に[[スパゲッティプログラム]]になりやすいアセンブリ言語のコードを読みやすくするものだった。1980年代にはこの手法が広まった。

独特の設計として、[[:en:Whitesmiths|Whitesmiths Ltd.]]([[Unix系]]OS [[:en:Idris (operating system)|Idris]] や[[C言語|C]][[コンパイラ]]で有名)が開発した8080/[[Z80]]プロセッサ用「ストリーム指向」アセンブラ A-natural がある。この言語はオペコードや[[レジスタ (コンピュータ)|レジスタ]]、メモリ参照といった要素をそのまま扱えるためアセンブラと呼ばれているが、実行順序を示す構文を取り入れていた。括弧やその他の記号でプログラムのブロック構造を指定したり、生成した命令列の実行順序を制御できる。A-natural は同社のCコンパイラが中間コードとしており、人間が直接使うものではなかったが、その論理的構文にはファンも存在した。

また構造化プログラミングとは若干異なるが、[[キャリーラボ]]は[[BASIC]]風の文法のアセンブリ言語 BASE を開発した。[[Z80]]用の BASE-80 と[[MC6809]]用の BASE-09 がある。BASEの表記例は下記の通り(BASE-09)


<source lang="asm">
<source lang="asm">
107行目: 171行目:
</pre>
</pre>


その後、アセンブリ言語で大規模システムを開発することが少なくなり、アセンブリ言語の高機能化の需要が減っていった<ref name="assembly-language?cat=technology">{{Cite web |url= http://www.answers.com/topic/assembly-language?cat=technology |title=assembly language: Definition and Much More from Answers.com |accessdate=2008-06-19 |author=Answers.com}}</ref>。それでも、資源の制約が強い場合やターゲットシステムのアーキテクチャが高水準言語の効率的使用を妨げている場合、アセンブラは有用であり、高機能なアセンブラの開発も行われている<ref>[http://neshla.sourceforge.net/ NESHLA: The High Level, Open Source, 6502 Assembler for the Nintendo Entertainment System]</ref>。
== 参照 ==

<references />
== 利用 ==
=== 歴史的観点 ===
アセンブリ言語は[[プログラム内蔵方式]]のコンピュータの黎明期に登場した。[[EDSAC]] (1949) には ''initial orders'' という1文字のニーモニックを採用したアセンブラが存在した<ref>{{Cite book| last1 = Salomon | title = Assemblers and Loaders | url = http://www.davidsalomon.name/assem.advertis/asl.pdf | accessdate = 2012-01-17 | page = 7 }}</ref>。[[ナサニエル・ロチェスター]]は1954年に [[IBM 701]] 用アセンブラを書いている。1955年、Stan Poley が [[IBM 650]] 用アセンブり言語 SOAP (Symbolic Optimal Assembly Program) を開発した<ref>{{Cite web| url = http://www.columbia.edu/cu/computinghistory/650.html | title = The IBM 650 Magnetic Drum Calculator | accessdate = 2012-01-17}}</ref>。

アセンブリ言語は、初期のコンピュータでのプログラミングでの入力ミス削減や時間短縮に貢献し、機械語コード参照やアドレス計算といった退屈な作業からプログラマを解放した。その後[[高水準言語]]へと移行していったが、ハードウェアの直接操作、特殊命令の使用、性能向上といった目的で今もアセンブリ言語が使われている。特に[[デバイスドライバ]]、[[組み込みシステム]]、[[リアルタイムシステム]]でよく使われている。

歴史的には多数のプログラムがアセンブリ言語だけで書かれてきた。[[ALGOL]]の方言である[[:en:Executive Systems Problem Oriented Language|ESPOL]]で書かれた [[:en:Burroughs MCP|Burroughs MCP]] (1961) が登場するまで、オペレーティングシステムはアセンブリ言語で書くのが普通だった。商用アプリケーションもアセンブリ言語で書かれており、例えば[[IBM]]の[[メインフレーム]]用ソフトウェアの多くはアセンブリ言語で書かれていた。[[COBOL]]、[[FORTRAN]]、[[PL/I]] などが取って代わっていったが、1990年代になってもアセンブリ言語のコードベースを保守し続けていた大企業も少なくない。

初期の[[マイクロコンピュータ]]ではアセンブリ言語がよく使われ、OSやアプリケーションも当初はアセンブリ言語で書かれた。これはリソースの制約が厳しかったためであり、メモリやディスプレイのアーキテクチャが特殊だったためでもある。また、マイクロコンピュータ向けの高水準言語のコンパイラがなかったという面も重要である。また、初期のマイクロコンピュータのユーザーはホビーストが主であり、何でも自前で作るという精神もそれに影響していたと見られる。

商用製品でアセンブリ言語を使う最大の理由は、使用メモリ量を最小にし、オーバーヘッドを最小にし、性能と信頼性を向上させるためである。

例えば、[[IBM PC]] の[[DOS (OS)|DOS]]や[[表計算ソフト]] [[Lotus 1-2-3]] などはアセンブリ言語で書かれていた。1990年代に入っても[[コンシューマーゲーム]]の多くはアセンブリ言語で書かれていた。ある業界関係者は[[セガサターン]]の最高性能を引き出して[[プレイステーション]]に対抗するにはアセンブリ言語を使うしかなかったとしている(プレイステーションにはソニーが提供するCライブラリが存在した)<ref>[http://www.eidolons-inn.net/tiki-index.php?page=SegaBase+Saturn Eidolon's Inn : SegaBase Saturn]</ref>。また、アーケードゲームの[[NBAジャム (ゲーム)|NBAジャム]] (1993) もアセンブリ言語で開発されている。1980年代から1990年代にかけての[[ホームコンピュータ]]([[ZX Spectrum]]、[[コモドール64]]、[[Amiga]]、[[Atari ST]] など)でもアセンブリ言語がよく使われていた。というのもそれらのBASICは性能が低く、ハードウェアの全機能を利用できないことが多かったためである。例えばAmigaには[[フリーウェア]]のアセンブリ言語[[統合開発環境]] [http://www.theflamearrows.info/homepage.html ASM-One assembler] があり、[[Microsoft Visual Studio]] に匹敵する機能を備えていた。

Don French が開発した [[VIC-1001|VIC-20]] 用アセンブラは 1,639 バイトという小ささで、世界一小さいアセンブラと言われている。アドレスをシンボルで表現でき、各種アドレス計算(四則演算、AND、OR、冪乗など)が可能だった<ref>{{Cite web |url= http://www.radiks.net/~jimbo/art/int7.htm |title=Speaking with Don French : The Man Behind the French Silk Assembler Tools |date=2004-05-21 |accessdate=2008-07-25 |author=Jim Lawless |publisher= | archiveurl= http://web.archive.org/web/20080821105848/http://www.radiks.net/~jimbo/art/int7.htm | archivedate= 21 August 2008| deadurl= no}}</ref>。

=== 現代における使用 ===
アセンブリ言語と高水準言語を比較した有用性と性能についての議論は、これまでよく行われてきた。アセンブリ言語は後述するように特定の用途で重要な役割を演じている。しかし一般的には[[コンパイラ最適化|最適化コンパイラ]]が人手で書かれたアセンブリ言語のコードと同等の性能を発揮すると言われている<ref>{{Cite web |last=Rusling |first=David A. |title=The Linux Kernel |url= http://tldp.org/LDP/tlk/basics/sw.html |accessdate=2012-03-11}}</ref>(例外もある<ref name="goto">{{Cite web |url= http://www.nytimes.com/2005/11/28/technology/28super.html?_r=1 |title=Writing the Fastest Code, by Hand, for Fun: A Human Computer Keeps Speeding Up Chips |publisher=New York Times, John Markoff |date=2005-11-28 |accessdate=2010-03-04}}</ref><ref name="bit-fild">{{Cite web |url= http://hardwarebug.org/2010/01/30/bit-field-badness/ |title=Bit-field-badness |publisher=hardwarebug.org |date=2010-01-30 |accessdate=2010-03-04| archiveurl= http://web.archive.org/web/20100205120952/http://hardwarebug.org/2010/01/30/bit-field-badness/| archivedate= 5 February 2010 | deadurl= no}}</ref><ref name="gcc-mess">{{Cite web |url= http://hardwarebug.org/2009/05/13/gcc-makes-a-mess/ |title=GCC makes a mess |publisher=hardwarebug.org |date=2009-05-13 |accessdate=2010-03-04| archiveurl= http://web.archive.org/web/20100316212040/http://hardwarebug.org/2009/05/13/gcc-makes-a-mess/| archivedate= 16 March 2010 | deadurl= no}}</ref>)。最近のプロセッサやメモリサブシステムは複雑化してきたため、コンパイラでもアセンブリ言語でも効果的な最適化がますます困難になってきている<ref name="GreatDebate1">{{Cite web |url= http://webster.cs.ucr.edu/Page_TechDocs/GreatDebate/debate1.html|title=The Great Debate|date=|accessdate=2008-07-03|author=Randall Hyde| archiveurl= http://web.archive.org/web/20080616110102/http://webster.cs.ucr.edu/Page_TechDocs/GreatDebate/debate1.html| archivedate= 16 June 2008 | deadurl= no}}</ref><ref name="compiler-fails1">{{Cite web |url= http://hardwarebug.org/2008/11/28/codesourcery-fails-again/ |title=Code sourcery fails again|publisher=hardwarebug.org |date=2010-01-30 |accessdate=2010-03-04| archiveurl= http://web.archive.org/web/20100402221204/http://hardwarebug.org/2008/11/28/codesourcery-fails-again/| archivedate= 2 April 2010 | deadurl= no}}</ref>。さらに言えば、プロセッサが高性能化するにしたがって[[入出力]]や[[ページング方式|ページング]]による遅延が無視できないレベルとなったため、コーディングによる性能追求は多くのプログラマにとって大きな問題ではなくなってきている。

開発者がアセンブリ言語を選択する状況として、次のようなものがある。
* 限られた資源で単独で動作する小さな実行ファイルが必要とされ、高水準言語のランタイム環境や[[ライブラリ]]が使えない場合。アセンブリ言語を使う状況としては最も一般的である。例えば、電話機のファームウェア、自動車の燃料・点火システム、空調システム、セキュリティシステム、センサーなどがある。
* [[デバイスドライバ]]や[[割り込みハンドラ]]、[[ブート]]コード、[[Basic Input/Output System|BIOS]]、[[Power On Self Test|POST]]など、ハードウェアと直接やりとりするコード。
* コンパイラでは実装されていないプロセッサ固有の命令を使わなければならないプログラム。例えば、[[暗号解読]]アルゴリズムでよく使われる[[ビット演算#(キャリーなし)ローテート|ビット単位ローテート]]命令を使うためにアセンブリ言語を使用する。
* [[コンパイラ最適化|コンパイラの最適化]]では不可能な、[[SIMD]]命令を駆使した[[最適化 (情報工学)|最適化]]などを手作業で行いたい場合。
* 極端な最適化を必要とするプログラム(例えば、プロセッサ集約型アルゴリズム内の内側の[[ループ (プログラミング)|ループ]]など)。例えば[[コンピュータゲーム]]開発においては、システムのハードウェア機能を最大限に発揮するようアセンブリ言語を使うことがある。また大規模な科学シミュレーションでも高度に最適化されたアルゴリズムを必要とし、例えば[[線型代数学]]の[[Basic Linear Algebra Subprograms|BLAS]]<ref name="goto"/><ref name="bench">{{Cite web |url= http://eigen.tuxfamily.org/index.php?title=Benchmark-August2008 |title=BLAS Benchmark-August2008 |publisher=eigen.tuxfamily.org |date=2008-08-01 |accessdate=2010-03-04}}</ref>や[[離散コサイン変換]](例えば[[x264]]のSIMDアセンブリ版<ref>{{Cite web |url= http://git.videolan.org/?p=x264.git;a=tree;f=common/x86;hb=HEAD |title=x264.git/common/x86/dct-32.asm |publisher=git.videolan.org |date=2010-09-29 |accessdate=2010-09-29}}</ref>)がアセンブリ言語で書かれている。
* 新たなプロセッサや特殊なプロセッサなど、高水準言語が存在しない場合。
* 次のような正確なタイミングを必要とするプログラム。
** シミュレーション、航空航法システム、医療装置などの[[リアルタイムシステム|リアルタイム]]プログラム。例えば[[フライ・バイ・ワイヤ]]システムでは、[[遠隔測定法|テレメトリ]]を厳密な制限時間内に解釈して対応する必要がある。そのようなシステムでは予測不能な遅延の原因を排除する必要があり、自動[[ガベージコレクション]]を伴う[[インタプリタ]]や[[ページフォルト]]を伴う[[仮想記憶]]や[[プリエンプション|プリエンプティブ・マルチタスク]]を避けなければならない。高水準言語の中には、ランタイム環境やOSインタフェースによってそのような遅延を生じるものがある。アセンブリ言語や低水準言語を選択することで、処理の詳細な部分まで目が行き届く。
** 暗号アルゴリズムは常に厳密に同じ時間で実行することで、{{仮リンク|タイミング攻撃|en|timing attack}}を防ぐ。
* 高度なセキュリティが要求され、環境を完全に制御する必要がある場合。
* [[コンピュータウイルス]]、[[ブート|ブートローダ]]、一部の[[デバイスドライバ]]など、ハードウェアと密接に連携するソフトウェア。
* 監視・トレース・[[デバッグ]]のための[[命令セットシミュレータ]]で、追加のオーバーヘッドを最小に保ちたい場合。
* 次のような[[リバースエンジニアリング]]またはプログラムファイルの改造。この場合[[逆アセンブラ]]が併用される。
** [[ソースコード]]が失われた(または入手できない)[[バイナリ]]ファイルがあるとき、それを改造する場合。あるいはソフトウェアの[[コピープロテクト]]を(不正に)解除する場合。
** [[テレビゲーム]]の改造。アセンブリ言語レベルでの改造がよく行われている。
* [[自己書き換えコード]]
* {{仮リンク|グラフ電卓|en|graphing calculator}}向けのソフトウェア開発<ref>{{Cite web |url= http://tifreakware.net/tutorials/89/a/calc/fargoii.htm |title=68K Programming in Fargo II |accessdate=2008-07-03 | archiveurl= http://web.archive.org/web/20080702181616/http://tifreakware.net/tutorials/89/a/calc/fargoii.htm | archivedate= 2 July 2008 | deadurl= no}}</ref>

[[計算機科学]]や[[情報工学]]では、アセンブリ言語が今も教えられている。実際にアセンブリ言語を使用するプログラマは全体から見れば少ないが、その概念は非常に重要である。[[二進法]]、[[メモリ管理]]、[[スタック]]処理、[[文字コード]]、[[割り込み (コンピュータ)|割り込み]]処理、[[コンパイラ]]設計といった基本的トピックは、ハードウェアレベルでのコンピュータの動作を学ばなければ深く理解するのが困難である。コンピュータの動作は基本的には[[命令セット]]で定義されるので、アセンブリ言語を学ぶことでそのような概念を習得できる。最近のコンピュータの命令セットはどれも似ている。したがって、どれか1つのアセンブリ言語を学ぶだけで、基本概念、どんなときにアセンブリ言語を使用するのが適しているか、高水準言語から効率的な実行コードを生成する方法を学習できる<ref>{{Cite web |url= http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/fwd.html |title=Foreword ("Why would anyone learn this stuff?"), ''op. cit.''|date=1996-09-30 |accessdate=2010-03-05 |author=Hyde, Randall | archiveurl= http://web.archive.org/web/20100325155048/http://www.arl.wustl.edu/~lockwood/class/cs306/books/artofasm/fwd.html | archivedate= 25 March 2010 | deadurl= no}}</ref>。これは、子どもが算数([[筆算]]など)を学ぶ必要があるが、日常の計算には[[電卓]]を使っているのに似ている。

=== アセンブラとコンパイラ ===
* 多くのコンパイラは高水準言語から直接機械語を生成せずにアセンブリ言語のコードを生成してからアセンブラに通す。それによりアセンブリ言語のコードを[[デバッグ]]や最適化に用いることができる。その意味ではアセンブリ言語は、目に見えない形ではあるが最も利用頻度の高いプログラミング言語といえる。
* 比較的低水準言語に近い[[C言語]]などでは、[[インラインアセンブラ]]を使うことで、ソース中にアセンブリ言語による記述を含めることができる。例えば[[Linuxカーネル]]などでそのような機能を利用しており、プログラムで実行時間の多くを占める部分をインラインアセンブラによる記述に置き換えることで、全体をアセンブリ言語で書いたプログラムに近い実行速度を実現できることもあるが、特定のCPUのアーキテクチャに依存する記述となるので互換性や[[移植性]]は大きく損なわれる。
* 分割コンパイルで作成するプログラムの一部のモジュールをアセンブリ言語で書くこともある。この場合、コンパイラの[[呼出規約]]にしたがってアセンブリ言語の[[プロシージャ]]を書き、コンパイラが生成した[[オブジェクトファイル|オブジェクト]]や[[ライブラリ]]と、アセンブラが生成したそれらを、対応した[[リンケージエディタ|リンカ]]で結合する。

== 主なアセンブラ ==
* [[IBM High Level Assembler|IBM High Level Assembler (HLASM)]] - [[IBM]]系[[メインフレーム]]用のアセンブラ。
* [[PDP-8#プログラム例|PDP-8のアセンブリ言語]] - PAL-III (Program Assembly Language III)
* [[CAP-X]] - CASL 以前に情報処理技術者試験で使われていたアセンブリ言語
* [[CASL]] - [[情報処理技術者試験]]用に作られたアセンブリ言語。同時に定義されているペーパーマシンCOMET用
* [[:en:As (Unix)|as]] - [[UNIX]]用のアセンブラ
* [[GNUアセンブラ|GNUアセンブラ (gas)]] - [[GNU]]が開発する、[[x86]]、[[MC68000|680x0]]、[[SPARC]]、[[VAX]]などの各種CPU用のアセンブラ
* [[Microsoft Macro Assembler|Microsoft Macro Assembler (MASM)]] - [[インテル]]のx86 CPU用に[[マイクロソフト]]が開発したアセンブラ
* [[Netwide Assembler|Netwide Assembler (nasm)]] - MASMと互換性の高いx86 CPU用アセンブラ
* [[Turbo Assembler|Turbo Assembler (TASM)]] - [[ボーランド]]が開発していた、MASMと互換性の高いx86 CPU用アセンブラ

[[Unix系]]システムでは、アセンブラを as と呼ぶのが一般的だが、実体はそれぞれのOSで異なる。[[GNUアセンブラ]]を使っているものが多い。

同じ系統のプロセッサであっても、複数のアセンブリ言語の方言が存在する。アセンブラによっては他の方言のアセンブリ言語も使用可能な場合がある。例えば、[[Turbo Assembler|TASM]]は[[Microsoft Macro Assembler|MASM]]用コードを入力として受け付け可能だが、逆は不可能である。{{仮リンク|FASM|en|FASM}}と[[Netwide Assembler|NASM]]は文法がほぼ同じだが、サポートしているマクロが異なるため、相互の翻訳は困難である。いずれも基本機能は同じだが、追加機能に差異がある<ref name="Hyde">{{Cite web |url = http://webster.cs.ucr.edu/AsmTools/WhichAsm.html |title = Which Assembler is the Best? |accessdate = 2007-10-19 |author = Randall Hyde | archiveurl= http://web.archive.org/web/20071018014019/http://webster.cs.ucr.edu/AsmTools/WhichAsm.html | archivedate= 18 October 2007 | deadurl= no}}</ref>。

== 脚注 ==
{{Reflist|group="注"}}

== 出典 ==
{{Reflist|colwidth=30em}}

== 参考文献 ==
* Jonathan Bartlett: ''[http://programminggroundup.blogspot.com/ Programming from the Ground Up]''. Bartlett Publishing, 2004. ISBN 0-9752838-4-7<br />Also available online [http://download.savannah.gnu.org/releases-noredirect/pgubook/ProgrammingGroundUp-1-0-booksize.pdf as PDF]
* Robert Britton: ''MIPS Assembly Language Programming''. Prentice Hall, 2003. ISBN 0-13-142044-5
* Paul Carter: ''PC Assembly Language''. Free ebook, 2001.<br />[http://drpaulcarter.com/pcasm/ Website]
* Jeff Duntemann: ''Assembly Language Step-by-Step''. Wiley, 2000. ISBN 0-471-37523-3
* Randall Hyde: ''The Art of Assembly Language''. No Starch Press, 2003. ISBN 1-886411-97-2
* Peter Norton, John Socha, ''Peter Norton's Assembly Language Book for the IBM PC'', Brady Books, NY: 1986.
* Michael Singer, ''PDP-11. Assembler Language Programming and Machine Organization'', John Wiley & Sons, NY: 1980.
* Dominic Sweetman: ''See MIPS Run''. Morgan Kaufmann Publishers, 1999. ISBN 1-55860-410-3
* John Waldron: ''Introduction to RISC Assembly Language Programming''. Addison Wesley, 1998. ISBN 0-201-39828-1


== 関連項目 ==
== 関連項目 ==
* [[逆アセンブラ]]
* [[逆アセンブラ]]
* [[コンパイラ|コンパイル]]
* [[コンパイラ|コンパイル]]
* [[低級言語]]
* [[高級言語]]
* [[マクロ (コンピュータ用語)]]
* [[マクロ (コンピュータ用語)]]
* [[命令セット]]

== 外部リンク ==
* [http://www.atariarchives.org/mlb/introduction.php Machine language for beginners]
* [http://www.int80h.org/ Unix Assembly Language Programming]
* [http://www-03.ibm.com/systems/z/os/zos/bkserv/r8pdf/index.html#hlasm IBM High Level Assembler] IBMのメインフレーム用アセンブリ言語のマニュアル
* [http://c2.com/cgi/wiki?LearningAssemblyLanguage PPR: Learning Assembly Language]
* [http://www.azillionmonkeys.com/qed/asmexample.html Assembly Language Programming Examples]
* [http://www.grc.com/smgassembly.htm Authoring Windows Applications In Assembly Language]
* [http://mark.masmcode.com/ Assembly Optimization Tips] by Mark Larson
* [http://nasm.sourceforge.net/doc/nasmdoc0.html NASM Manual]
* [http://www.softools.com/sasmzilog.htm Z80/Z180/8085 Assembler]


{{DEFAULTSORT:あせんふりけんこ}}
{{Computer-stub}}
[[Category:プログラミング言語|あせんふりけんこ]]
[[Category:プログラミング言語]]
[[Category:アセンブリ言語|*]]
[[Category:アセンブリ言語|*]]
[[Category:アセンブラ|*]]
[[Category:アセンブラ|*]]

2012年11月3日 (土) 01:39時点における版

モトローラ MC6800 のアセンブリ言語のソースコード

アセンブリ言語(アセンブリげんご、assembly language)とは、コンピュータマイクロコントローラ、その他のプログラム可能な機器を動作させるための機械語を人間にわかりやすい形で記述する、代表的な低水準言語である。

概要

プロセッサが直接実行できる言語は機械語のみであるが、機械語はバイナリ(数値)の羅列なので人間には理解しにくい。そこで、機械語を直接記述するのではなく、ニーモニックと呼ばれる命令語でプログラムを記述することで、人間により分かりやすくしたものがアセンブリ言語である。アセンブリ言語の意味は個々のプロセッサに依存するため、高水準言語のような移植性はない。

アセンブリ言語で書かれたプログラムを機械語プログラムに変換する事をアセンブル (assemble) すると言い、それを行うプログラムの事をアセンブラ (assembler) と言う。なお、アセンブリ言語の意味で「アセンブラ」または「アセンブラ言語」(Assembler Language)と呼ぶ場合も多い[注 1][1]

初期のコンピュータでは「アセンブラ」を「アセンブリプログラム」と呼ぶ例もあった[2]

アセンブリ言語の命令は、アセンブラに対する命令(疑似命令)やマクロ命令を除き、基本的には[注 2]機械語と1対1で対応し、プログラマがCPUの動作を把握しながらプログラムを記述する事ができる。

アセンブリ言語ではマシンの低水準な操作またはオペコードニーモニックで表す。オペコードによっては、機械語命令の一部として1つまたは複数のオペランドが必要である。また、多くのアセンブリ言語はオペランドとしてラベルやシンボルを使ってアドレスや定数を表すことができ、それらの値をプログラム内にそのまま書く(ハードコーディング)のを防ぐことができる。マクロアセンブラマクロ命令機能を備えており、アセンブリ言語のテキストに名前を事前に割り当て、その名前を使うことで他のコードにそのテキストを挿入できる。多くのアセンブラは、プログラム開発を支援したり、アセンブリ過程を制御したり、デバッグを支援したりといった付加機構を備えている。

歴史

機械語は、実行したい計算の内容をCPUの内部構造に依存した非常に単純な操作に分割・変換したものであるため、人間には理解しづらい。機械語を並べながらプログラミングするのは、人間のプログラマにとっては負担が大きかった。

そこで、機械語そのものを書く代わりに機械語の「意味」に相当する短い記号や単語を対応させ、それを記述してプログラミングをすることが考えられた。

世界で最初に実用的に稼働したノイマン型電子計算機とされるEDSACのローダ(外部記憶装置からプログラムやデータを読み出して主記憶装置に書き込むプログラム)において、既に原始的なアセンブラの機能が実装されている。EDSACはワード指向アーキテクチャで命令長が1ワードの固定長命令のマシンであり、入力装置は紙テープでありキャラクタ指向である。紙テープ上の A 1 0 0 F という文字列から十進法を数値に変換するなどの処理をおこない、「100番地の値をアキュムレータに加算する」という1ワードの命令を生成する、といった機能が、EDSACのローダには実装されていた。

機械語への変換は人間が手で行うこともあり、ハンド・アセンブルと呼ぶ。単に定められた規則に従って記号や単語から機械語を生成するだけなので、自動的に機械語を出力するプログラムが作られるようになった。このプログラムをアセンブラという。

コンピュータの歴史の初期には、このような、プログラムによって機械語プログラムを生成することを自動プログラミングと呼んだ。

ドナルド・ギリースには、まだ発明されていなかったアセンブラを開発中に、フォン・ノイマンに開発を即座に止めるように言われたという、1950年代初期ならではの逸話がある。というのも、当時は人間が手作業でもできるような瑣末な仕事をコンピュータにさせるような時代が来るとは考えられておらず、単に時間の無駄だと考えられた(ノイマンには[注 3])のである。

主要概念

アセンブラ

アセンブラは、アセンブリ命令ニーモニックをオペコードに変換し、シンボル名をメモリ位置や他の実体に変換することでオブジェクトコードを生成する[3]。シンボル名による参照の利用はアセンブラの重要な機能であり、面倒な計算やプログラム修正に伴うアドレスの更新の手間を省くことができる。多くのアセンブラはマクロ機能を備えており、よく使用する命令列をサブルーチン呼び出しではなくインライン展開することができる。

パス回数

実行ファイルを生成するのにソースファイルを何回パス(走査)するかでアセンブラを分類できる。

ワンパスアセンブラ
ソースコードを1回だけパスするアセンブラ。定義される前にシンボルが使われているとオブジェクトコードの最後に "errata" を置く必要があり、リンカまたはローダが未定義シンボルが使われていた位置にあるプレースホルダーを書き換える。あるいは、未定義なシンボルを使用するとエラーになる。
マルチパスアセンブラ
最初のパスで全シンボルとその値の表を作成し、その表を使ってその後のパスでコードを生成する。

どちらの場合も、アセンブラは最初のパスで各命令のサイズを確定させる必要があり、それによって後に出現するシンボルのアドレスを計算する。命令のサイズは後から定義されるオペランドの型や距離に依存することがあるため、アセンブラは最初のパスでは悲観的な見積もりをし、必要に応じてその後のパスまたは errata にて1つ以上のNOP命令(何もしない命令)を挿入してすき間を生める必要がある。最適化を行うアセンブラでは、最初の悲観的コードをその後のパスで稠密なコードに書き換えてアドレスの再計算を行うことがある。

もともとワンパスアセンブラは高速であるためよく使われていた。マルチパス動作をするには、磁気テープを巻き戻したりパンチカードのデッキをセットし直して読み込む必要があったためである。現代のコンピュータではマルチパスであってもそのような遅延は生じない。マルチパスアセンブラは errata がないため、リンク処理(アセンブラが直接実行コードを生成する場合はローダの処理)が高速化される[4]

高水準アセンブラ

より洗練された高水準アセンブラ英語版は言語として次のような抽象化を提供する。

クロスアセンブラとメタアセンブラ

クロスアセンブラクロスコンパイラと似ており、あるプラットフォームで動作するが、そのプラットフォームではなく別のプラットフォーム向けのオブジェクトコードを生成するアセンブラを指す。小型の組み込みシステムなど、対象システムでアセンブラを動作させられない場合に使用することが多い。その場合、生成した機械語コードを対象システムに転送する何らかの手段が必要である。単に機械語コードをバイト単位に転送することもできるが、ASCII表現の転送用フォーマットがメーカーから提供されている(モトローラのSREC、インテルのHEXなど)。

メタアセンブラは、アセンブリ言語の文法や意味論を記述したものを入力とし、その言語のためのアセンブラを出力するプログラムである[6]

アセンブリ言語

アセンブリ言語で書かれたプログラムは、プロセッサの命令に対応したニーモニックの列、ディレクティブや擬似命令と呼ばれるメタな文、コメント、データで構成されている。ニーモニックとは、機械語の命令がプロセッサでおこなう動作を表現する英単語ないしその省略(LoadをLDなど)で表現したものである。通常の文はオペコードのニーモニックで始まり、パラメータ(データ、引数)のリストがそれに続く[7]。それらをアセンブラが機械語命令に翻訳し、メモリにロードして実行できる形式にする。

なかには、パイプライン処理などを最適化するために命令順序を入れ替えたり、ラベルの位置関係によってアドレッシングモードを最適化するアセンブラもあり、必ずしもソーステキストの記述とアセンブルの結果が直接対応するとは限らない。

オペランドにはソースとデスティネーションの二種類があり、データとして読み取られるのがソースで、オペコードで示された命令の実行結果が格納されるのがデスティネーションである。ソースには定数・レジスタ・メモリのいずれか、デスティネーションにはレジスタ・メモリのいずれかを指定する。

なお、オペランドの記述順序は、上の例では「デスティネーション, ソース」だが、「ソース, デスティネーション」の順に書くアセンブリ言語もある。また、オペランドの個数は命令によって異なり、典型的なオペランドは0以上のソースと1つのデスティネーションからなるが、プロセッサにより、暗黙のソースやデスティネーションを持つためにそれらを記述しない命令や、オペランドを持たない命令を持つ場合もある。

例えば、次の命令はx86/IA-32プロセッサのもので、8ビット即値レジスタに入れる命令である。この命令のバイナリコードは 10110 で、その後に3ビットのレジスタを指定する識別子が続く。AL レジスタの識別子は 000 なので、次に示す機械語AL レジスタに 01100001 というデータをロードする[8]

10110000 01100001

このバイナリコードを人間が読みやすいように十六進法で表現すると次のようになる。

B0 61

ここで、B0 は「ALに後続の値をコピーする」ことを意味し、61 は 01100001 を十六進法で表したもの(十進法では 97)である。インテルのアセンブリ言語では、この種の命令に MOV というニーモニックを割り当てており、セミコロン以下に説明的コメントを添えたアセンブリ言語での表現は次のようになる。

MOV AL, 61h       ; Load AL with 97 decimal (61 hex)

この場合、定数61Hがソース、レジスタALがデスティネーションに該当し、命令が実行されると、定数61Hが、レジスタALに単純に格納される。これが人間にとってはさらに読みやすく覚えやすい。

アセンブリ言語によっては、MOV のようなニーモニックはロードやデータのコピー/移動を行う命令群を表すのに使われ、オペランドの種類によって実際のオペコードが異なっていてもニーモニックとしては同じものを使う。また、データのコピー/移動の方向などによって別々のニーモニックを使うアセンブリ言語もある(「メモリからレジスタへの移動」を L、「レジスタからメモリへの移動」を ST、「レジスタからレジスタへの移動」を LR、「即値をメモリへ移動」を MVI など)。

インテルのオペコード 10110000 (B0) は8ビットの値を AL レジスタにコピーするが、10110001 (B1) は CL レジスタにコピーし、10110010 (B2) は DL レジスタにコピーする。これらをアセンブリ言語で表現すると次のようになる[8]

MOV AL, 1h        ; Load AL with immediate value 1
MOV CL, 2h        ; Load CL with immediate value 2
MOV DL, 3h        ; Load DL with immediate value 3

MOVの構文には次の例のようにさらに複雑なものもある[9]

MOV EAX, [EBX]	  ; Move the 4 bytes in memory at the address contained in EBX into EAX
MOV [ESI+EAX], CL ; Move the contents of CL into the byte at address ESI+EAX

MOV というニーモニックを使った文は、その内容によってアセンブラが 88-8E、A0-A3、B0-B8、C6、C7 のいずれかのオペコードに変換するので、プログラマはオペコードを知る必要がないし、オペコードを覚える必要もない[8]

アセンブリ言語から機械語への変換はアセンブラが行うが、逆方向の変換の一部は逆アセンブラが行う。高水準言語とは異なり、単純なアセンブリ構文と機械語命令には1対1の関係がある。しかしアセンブラは擬似命令(マクロの一種)を提供していることがあり、1つの擬似命令をよく使われる機械語命令列に展開する。例えば、大小比較による条件分岐命令を持たないマシンの場合、アセンブラで大小比較命令とゼロなら分岐する条件分岐命令(比較命令の結果を使用)に展開される擬似命令を用意したりする。多くの高機能アセンブラは豊富なマクロ言語機能を備えており、複雑なコード列やデータシーケンスを生成できる。

コンピュータ・アーキテクチャはそれぞれ独自の機械語を持つ。アーキテクチャが異なれば、サポートする命令の数や種類が異なり、レジスタの大きさや個数が異なり、データの格納形式が異なる。汎用コンピュータの多くは機能的にほぼ同等だが、実装は異なるので、アセンブリ言語にはその差異が反映されている。

機械語の命令セットは、プロセッサによって異なる。命令セットが同じでも様々なニーモニックやアセンブリ言語の文法が存在しうる。一般にプロセッサの設計者あるいは製造者によって定義されたニーモニックが標準とされるが、アセンブラによってはこれと異なるニーモニックを用いる場合もある(GNUアセンブラのgasのインテルプロセッサ用など)。

言語設計

基本要素

アセンブラの開発者によって用語の使い方に大きな差異があり、文の分類などが異なる。例えば、マシンのニーモニックや拡張ニーモニック以外は全て擬似命令と呼ぶ場合もある。典型的なアセンブリ言語は、プログラムの操作の定義に使われる命令文を以下の3種類に分類する。

  • オペコードのニーモニック
  • データセクション
  • アセンブリディレクティブ

オペコードのニーモニックと拡張ニーモニック

アセンブリ言語の命令文は一般に非常に単純で、高水準言語のそれとは異なる。一般にニーモニックは1つの機械語命令(オペコード)のシンボル名であり、個々の機械語命令には少なくとも1つのオペコード・ニーモニックが対応している。命令は一般に「オペコード」と0以上の「オペランド」で構成される。多くの命令は1つまたは2つの値を参照する。オペランドには即値(命令内に置かれる値)、レジスタ(暗黙のうちに使用される場合もある)、記憶装置内のデータの位置を示すアドレスなどがある。「拡張ニーモニック」はオペコードと特定オペランドの組合せを表すのに使われることが多い。例えばSystem/360では、BC 命令にマスク15を組み合わせたものが BBC 命令にマスク0を組み合わせたものが NOP という拡張ニーモニックで表される。

「拡張ニーモニック」は命令の特殊な用途をサポートするのに使われることが多く、本来の命令の名称からはその用途が連想できないときに使うことが多い。例えば、多くのCPUは明示的にNOP命令を用意していないが、その用途に使える命令は存在する。8086では xchg ax,ax という命令が nop として使えるので、アセンブリ言語で nop を記述すると xchg ax,ax という命令に変換される。逆アセンブラにもこのあたりを認識し、xchg ax,axnop に変換するものがある。同様にIBMのSystem/360System/370のアセンブラでは、拡張ニーモニック NOPNOPR を使用し、それぞれ BCBCR のマスク0の命令に変換する。SPARCアーキテクチャでは、拡張ニーモニックを synthetic instructions と呼んでいる[10]

アセンブラによっては単純な組み込みマクロ命令を備えており、数個の機械語命令に展開される。例えば一部のZ80用アセンブラでは、ld hl,bc というマクロ命令を ld l,cld h,b という2命令に展開する[11]

データセクション

データと変数を保持するデータ要素を定義するのに使われる命令文がある。データの型、長さ、境界(アライメント)を定義する。また、そのデータがプログラム外部(別ファイルでアセンブルされたプログラム)からも利用可能なのか、それともデータセクションを定義したプログラム内でのみ使用可能なのかも定義できる。一部のアセンブラはこれを擬似命令に分類している。

アセンブリディレクティブ

アセンブリディレクティブは擬似命令とも呼ばれ、アセンブラがアセンブリ実施中に実行すべき命令となっている[3]。プログラマが入力するパラメータによって異なった形でアセンブルが行われるよう指示することができる。また、プログラムの見た目を操作して、可読性と保守性を向上させるのにも使われる。例えば、記憶装置の領域を予約し、その初期内容を指定するディレクティブなどがある。ディレクティブの名称はドットで始まることが多く、それによって通常のニーモニックと区別している。

擬似オペコード (pseudo-opcode) と言った場合、オブジェクトコードを実際に生成するディレクティブのみを指すこともある[12]

ラベル/シンボル

シンボリックアセンブラでは、任意の名前(ラベルまたはシンボル)とメモリ位置を対応付けることができる。通常、定数や変数に名前をつけることができ、命令文ではそれらの位置を名前で参照できる。実行コードではサブルーチンのエントリポイントと名前を関連付け、サブルーチンを名前で呼び出すことができる。サブルーチン内では、分岐命令の分岐先をラベルで示すことができる。一部のアセンブラは「ローカルシンボル」をサポートしており、通常のシンボルとは語彙的に区別する(例えば、"10$" を分岐先に使用するなど)。

一部のアセンブラは柔軟なシンボル管理を提供しており、複数の名前空間を管理したり、データ構造内のオフセットを自動的に計算したり、リテラル値やアセンブラが実施した単純な計算結果を参照するラベルを割り当てたりすることができる。ラベルは定数や変数をリロケータブルなアドレスで初期化するのにも使える。

コメント

他の言語と同様アセンブリ言語でもソースコードにコメントを付与でき、アセンブラはそれらを無視できる。高水準言語に比べて可読性が低いため、コメントの重要性は高い。

これらの機能を多用することで低水準のコードのコーディングや保守の問題を大幅に単純化することができる。コンパイラや逆アセンブラが生成するアセンブリソースはコメントがなく、自動生成されるシンボルが意味不明で、データ定義もないため、非常に可読性が低い。

マクロ

多くのアセンブラは事前定義されたマクロをサポートしており、中にはユーザーが定義可能なマクロをサポートしているものもある。マクロは命令列と変数や定数の定義を埋め込むことができ、その中にオペコードやディレクティブの列が含まれる。マクロが定義されると、その名前をニーモニックとして使用できる。アセンブラはソース内にマクロを発見すると、対応するコード列に置き換え、元からソースにそのコード列が存在したかのように処理をする(アセンブラによっては、マクロを展開した中にマクロがあれば、それも展開することができる)。

なお、このような「マクロ」の定義は、例えばC言語でのマクロとは若干異なる。C言語のマクロは一般に #define というディレクティブで定義され、1行または多くても数行で済ませることが多い。アセンブラのマクロはそれ自体が長い「プログラム」であり、アセンブラがアセンブル時に解釈して実行する。

マクロは短い名前だが、数行からかなり長い行数のコードに展開されるので、アセンブリ言語のプログラムの見た目を短くすることができる。また、マクロによってアセンブリ言語プログラムに高水準の構造を追加でき、パラメータ付きのデバッグ用コードを埋め込むなどの利用法がある。

マクロアセンブラでは、マクロにパラメータを付与できる。中には洗練されたマクロ言語を備えたアセンブラもあり、オプションパラメータ、記号変数、条件文、文字列操作、算術演算などの高水準言語要素を持ち、マクロ実行中にそれらを使用でき、またマクロがコンテキストをセーブしたり情報を交換したりすることも可能である。したがってマクロの引数に基づいて大量のアセンブリ言語命令またはデータ定義を生成できる。例えば、レコード風のデータ構造や展開されたループを生成するのに使え、複雑なパラメータに基づいてアルゴリズム全体を生成することもできる。そのようなマクロで大いに拡張されたアセンブリ言語を使用すると、コンピュータの低水準の概念要素を扱う必要がなくなり、一種の高水準言語をつかっているのと同じことになる。

メインフレームの時代には、マクロは特定顧客の大規模ソフトウェアシステムのカスタマイズや、メーカーのオペレーティングシステムを顧客の要望に合わせた特注版にするのに使われていた。例えば、IBMVM/CMS、リアルタイムトランザクション処理用アドオン、CICSACP英語版/TPFコンピュータ予約システム (CRS) やクレジットカード会社で使われているトランザクションOS)などで使われてきた。

アセンブラのマクロ機能だけを全く異なる言語のコード生成に使うこともできる。例えば、COBOLのプログラムをマクロアセンブラのアセンブル時に実行されるオペレータで生成することができる。

というのも、1960年代に実用化された「マクロ処理」は「アセンブリ」とは独立した概念であり、マクロ処理は単なるオブジェクトコード生成というよりも現代的にはワードプロセッシングやテキストプロセッシングに近い。C言語にもマクロ処理の概念が導入されており、プリプロセッサと呼ばれる。ただし、アセンブラのマクロプロセッサはチューリング完全だったが、C言語のプリプロセッサはそうではない(Cのプリプロセッサにはループ機能や "goto" 機能がない)。

マクロ処理の能力は大きいが、アセンブラ以外の高水準言語ではあまり使われなくなった(例外としてC/C++とPL/Iがある)。

マクロのパラメータ置換は厳密に名前によってなされる。マクロ処理の際、パラメータ値がその名前を逐語的に置換する。そのため、パラメータとして式を指定したときよくあるバグが生じる。例えば次のようなマクロがあるとする。

foo: macro a
load a*b

このマクロは呼び出し側が変数名を指定し、広域変数または定数である b とその変数をかけることを想定している。しかし、foo のパラメータとして a-c を指定するとマクロは load a-c*b と展開されてしまう。これを防ぐにはマクロ定義内でパラメータを常に括弧で囲むか、呼び出し時にパラメータを括弧付きにするしかない[13]

構造化プログラミングサポート

構造化プログラミングの要素を取り入れたアセンブラもある。最初期の例として "Concept-14 macro set" がある。Dr. H.D. Mills (March, 1970) が提案し、IBMの連邦政府システム部門の Marvin Kessler が実装したもので、System/360 のマクロアセンブラに IF/ELSE/ENDIF などの制御構造を導入した[14]。これはアセンブリコードからGOTO操作を削減または排除するもので、本質的にスパゲッティプログラムになりやすいアセンブリ言語のコードを読みやすくするものだった。1980年代にはこの手法が広まった。

独特の設計として、Whitesmiths Ltd.Unix系OS IdrisCコンパイラで有名)が開発した8080/Z80プロセッサ用「ストリーム指向」アセンブラ A-natural がある。この言語はオペコードやレジスタ、メモリ参照といった要素をそのまま扱えるためアセンブラと呼ばれているが、実行順序を示す構文を取り入れていた。括弧やその他の記号でプログラムのブロック構造を指定したり、生成した命令列の実行順序を制御できる。A-natural は同社のCコンパイラが中間コードとしており、人間が直接使うものではなかったが、その論理的構文にはファンも存在した。

また構造化プログラミングとは若干異なるが、キャリーラボBASIC風の文法のアセンブリ言語 BASE を開発した。Z80用の BASE-80 とMC6809用の BASE-09 がある。BASEの表記例は下記の通り(BASE-09)

S[A,B,X,U
A=$80
A=A+$C0
S]A,B,X,U,PC

上記の記述は下記のアセンブラ表記に対応する。

PSHS A,B,X,U
LDA #$80
ADDA #$C0
PULS A,B,X,U,PC

その後、アセンブリ言語で大規模システムを開発することが少なくなり、アセンブリ言語の高機能化の需要が減っていった[15]。それでも、資源の制約が強い場合やターゲットシステムのアーキテクチャが高水準言語の効率的使用を妨げている場合、アセンブラは有用であり、高機能なアセンブラの開発も行われている[16]

利用

歴史的観点

アセンブリ言語はプログラム内蔵方式のコンピュータの黎明期に登場した。EDSAC (1949) には initial orders という1文字のニーモニックを採用したアセンブラが存在した[17]ナサニエル・ロチェスターは1954年に IBM 701 用アセンブラを書いている。1955年、Stan Poley が IBM 650 用アセンブり言語 SOAP (Symbolic Optimal Assembly Program) を開発した[18]

アセンブリ言語は、初期のコンピュータでのプログラミングでの入力ミス削減や時間短縮に貢献し、機械語コード参照やアドレス計算といった退屈な作業からプログラマを解放した。その後高水準言語へと移行していったが、ハードウェアの直接操作、特殊命令の使用、性能向上といった目的で今もアセンブリ言語が使われている。特にデバイスドライバ組み込みシステムリアルタイムシステムでよく使われている。

歴史的には多数のプログラムがアセンブリ言語だけで書かれてきた。ALGOLの方言であるESPOLで書かれた Burroughs MCP (1961) が登場するまで、オペレーティングシステムはアセンブリ言語で書くのが普通だった。商用アプリケーションもアセンブリ言語で書かれており、例えばIBMメインフレーム用ソフトウェアの多くはアセンブリ言語で書かれていた。COBOLFORTRANPL/I などが取って代わっていったが、1990年代になってもアセンブリ言語のコードベースを保守し続けていた大企業も少なくない。

初期のマイクロコンピュータではアセンブリ言語がよく使われ、OSやアプリケーションも当初はアセンブリ言語で書かれた。これはリソースの制約が厳しかったためであり、メモリやディスプレイのアーキテクチャが特殊だったためでもある。また、マイクロコンピュータ向けの高水準言語のコンパイラがなかったという面も重要である。また、初期のマイクロコンピュータのユーザーはホビーストが主であり、何でも自前で作るという精神もそれに影響していたと見られる。

商用製品でアセンブリ言語を使う最大の理由は、使用メモリ量を最小にし、オーバーヘッドを最小にし、性能と信頼性を向上させるためである。

例えば、IBM PCDOS表計算ソフト Lotus 1-2-3 などはアセンブリ言語で書かれていた。1990年代に入ってもコンシューマーゲームの多くはアセンブリ言語で書かれていた。ある業界関係者はセガサターンの最高性能を引き出してプレイステーションに対抗するにはアセンブリ言語を使うしかなかったとしている(プレイステーションにはソニーが提供するCライブラリが存在した)[19]。また、アーケードゲームのNBAジャム (1993) もアセンブリ言語で開発されている。1980年代から1990年代にかけてのホームコンピュータZX Spectrumコモドール64AmigaAtari ST など)でもアセンブリ言語がよく使われていた。というのもそれらのBASICは性能が低く、ハードウェアの全機能を利用できないことが多かったためである。例えばAmigaにはフリーウェアのアセンブリ言語統合開発環境 ASM-One assembler があり、Microsoft Visual Studio に匹敵する機能を備えていた。

Don French が開発した VIC-20 用アセンブラは 1,639 バイトという小ささで、世界一小さいアセンブラと言われている。アドレスをシンボルで表現でき、各種アドレス計算(四則演算、AND、OR、冪乗など)が可能だった[20]

現代における使用

アセンブリ言語と高水準言語を比較した有用性と性能についての議論は、これまでよく行われてきた。アセンブリ言語は後述するように特定の用途で重要な役割を演じている。しかし一般的には最適化コンパイラが人手で書かれたアセンブリ言語のコードと同等の性能を発揮すると言われている[21](例外もある[22][23][24])。最近のプロセッサやメモリサブシステムは複雑化してきたため、コンパイラでもアセンブリ言語でも効果的な最適化がますます困難になってきている[25][26]。さらに言えば、プロセッサが高性能化するにしたがって入出力ページングによる遅延が無視できないレベルとなったため、コーディングによる性能追求は多くのプログラマにとって大きな問題ではなくなってきている。

開発者がアセンブリ言語を選択する状況として、次のようなものがある。

計算機科学情報工学では、アセンブリ言語が今も教えられている。実際にアセンブリ言語を使用するプログラマは全体から見れば少ないが、その概念は非常に重要である。二進法メモリ管理スタック処理、文字コード割り込み処理、コンパイラ設計といった基本的トピックは、ハードウェアレベルでのコンピュータの動作を学ばなければ深く理解するのが困難である。コンピュータの動作は基本的には命令セットで定義されるので、アセンブリ言語を学ぶことでそのような概念を習得できる。最近のコンピュータの命令セットはどれも似ている。したがって、どれか1つのアセンブリ言語を学ぶだけで、基本概念、どんなときにアセンブリ言語を使用するのが適しているか、高水準言語から効率的な実行コードを生成する方法を学習できる[30]。これは、子どもが算数(筆算など)を学ぶ必要があるが、日常の計算には電卓を使っているのに似ている。

アセンブラとコンパイラ

  • 多くのコンパイラは高水準言語から直接機械語を生成せずにアセンブリ言語のコードを生成してからアセンブラに通す。それによりアセンブリ言語のコードをデバッグや最適化に用いることができる。その意味ではアセンブリ言語は、目に見えない形ではあるが最も利用頻度の高いプログラミング言語といえる。
  • 比較的低水準言語に近いC言語などでは、インラインアセンブラを使うことで、ソース中にアセンブリ言語による記述を含めることができる。例えばLinuxカーネルなどでそのような機能を利用しており、プログラムで実行時間の多くを占める部分をインラインアセンブラによる記述に置き換えることで、全体をアセンブリ言語で書いたプログラムに近い実行速度を実現できることもあるが、特定のCPUのアーキテクチャに依存する記述となるので互換性や移植性は大きく損なわれる。
  • 分割コンパイルで作成するプログラムの一部のモジュールをアセンブリ言語で書くこともある。この場合、コンパイラの呼出規約にしたがってアセンブリ言語のプロシージャを書き、コンパイラが生成したオブジェクトライブラリと、アセンブラが生成したそれらを、対応したリンカで結合する。

主なアセンブラ

Unix系システムでは、アセンブラを as と呼ぶのが一般的だが、実体はそれぞれのOSで異なる。GNUアセンブラを使っているものが多い。

同じ系統のプロセッサであっても、複数のアセンブリ言語の方言が存在する。アセンブラによっては他の方言のアセンブリ言語も使用可能な場合がある。例えば、TASMMASM用コードを入力として受け付け可能だが、逆は不可能である。FASM英語版NASMは文法がほぼ同じだが、サポートしているマクロが異なるため、相互の翻訳は困難である。いずれも基本機能は同じだが、追加機能に差異がある[31]

脚注

  1. ^ IBMはSystem/360から2011年現在まで一貫してアセンブラ言語(Assembler Language)と呼んでいる。例:IBM High Level Assembler
  2. ^ MIPSのアセンブラの一部など、命令の遅延分岐スロットへの移動を勝手に行うものもある。OPTASM(SLR社)という最適化アセンブラもあった。
  3. ^ 前述したように、1950年にはEDSACにおいて原始的なアセンブラが存在していた。時代背景というよりは、ノイマンや、チューリングにもこういったこぼれ話はあるが、そういった天才でも未来を全て知っているわけではない、という教訓であろう。

出典

  1. ^ Stroustrup, Bjarne, The C++ Programming Language, Addison-Wesley, 1986, ISBN 0-201-12078-X: "C++ was primarily designed so that the author and his friends would not have to program in assembler, C, or various modern high-level languages." - assemblerassembly language の意味で使っている例
  2. ^ Saxon, James, and Plette, William, Programming the IBM 1401, Prentice-Hall, 1962, LoC 62-20615. - assembly program という用語を使っている例
  3. ^ a b David Salomon (1993). Assemblers and Loaders
  4. ^ Beck, Leland L. (1996). “2”. System Software: An Introduction to Systems Programming. Addison Wesley 
  5. ^ Hyde, Randall. "Chapter 12 – Classes and Objects". The Art of Assembly Language, 2nd Edition. No Starch Press. © 2010.
  6. ^ (John Daintith, ed.) A Dictionary of Computing: "meta-assembler"
  7. ^ Intel Architecture Software Developer’s Manual, Volume 2: Instruction Set Reference. INTEL CORPORATION. (1999). http://download.intel.com/design/PentiumII/manuals/24319102.PDF 2010年11月18日閲覧。 
  8. ^ a b c Intel Architecture Software Developer’s Manual, Volume 2: Instruction Set Reference. INTEL CORPORATION. (1999). pp. 442 and 35. http://download.intel.com/design/PentiumII/manuals/24319102.PDF 2010年11月18日閲覧。 
  9. ^ Evans, David (2006年). “x86 Assembly Guide”. University of Virginia. 2010年11月18日閲覧。
  10. ^ The SPARC Architecture Manual, Version 8”. SPARC, International (1992年). 2012年10月27日閲覧。
  11. ^ http://www.z80.de/z80/z80code.htm
  12. ^ Microsoft Corporation. “MASM: Directives & Pseudo-Opcodes”. 2011年3月19日閲覧。
  13. ^ Macros (C/C++), MSDN Library for Visual Studio 2008”. Microsoft Corp.. 2010年6月22日閲覧。
  14. ^ Concept 14 Macros”. MVS Software. 2009年5月25日閲覧。
  15. ^ Answers.com. “assembly language: Definition and Much More from Answers.com”. 2008年6月19日閲覧。
  16. ^ NESHLA: The High Level, Open Source, 6502 Assembler for the Nintendo Entertainment System
  17. ^ Salomon. Assemblers and Loaders. p. 7. http://www.davidsalomon.name/assem.advertis/asl.pdf 2012年1月17日閲覧。 
  18. ^ The IBM 650 Magnetic Drum Calculator”. 2012年1月17日閲覧。
  19. ^ Eidolon's Inn : SegaBase Saturn
  20. ^ Jim Lawless (2004年5月21日). “Speaking with Don French : The Man Behind the French Silk Assembler Tools”. 21 August 2008時点のオリジナルよりアーカイブ。2008年7月25日閲覧。
  21. ^ Rusling, David A.. “The Linux Kernel”. 2012年3月11日閲覧。
  22. ^ a b Writing the Fastest Code, by Hand, for Fun: A Human Computer Keeps Speeding Up Chips”. New York Times, John Markoff (2005年11月28日). 2010年3月4日閲覧。
  23. ^ Bit-field-badness”. hardwarebug.org (2010年1月30日). 5 February 2010時点のオリジナルよりアーカイブ。2010年3月4日閲覧。
  24. ^ GCC makes a mess”. hardwarebug.org (2009年5月13日). 16 March 2010時点のオリジナルよりアーカイブ。2010年3月4日閲覧。
  25. ^ Randall Hyde. “The Great Debate”. 16 June 2008時点のオリジナルよりアーカイブ。2008年7月3日閲覧。
  26. ^ Code sourcery fails again”. hardwarebug.org (2010年1月30日). 2 April 2010時点のオリジナルよりアーカイブ。2010年3月4日閲覧。
  27. ^ BLAS Benchmark-August2008”. eigen.tuxfamily.org (2008年8月1日). 2010年3月4日閲覧。
  28. ^ x264.git/common/x86/dct-32.asm”. git.videolan.org (2010年9月29日). 2010年9月29日閲覧。
  29. ^ 68K Programming in Fargo II”. 2 July 2008時点のオリジナルよりアーカイブ。2008年7月3日閲覧。
  30. ^ Hyde, Randall (1996年9月30日). “Foreword ("Why would anyone learn this stuff?"), op. cit.”. 25 March 2010時点のオリジナルよりアーカイブ。2010年3月5日閲覧。
  31. ^ Randall Hyde. “Which Assembler is the Best?”. 18 October 2007時点のオリジナルよりアーカイブ。2007年10月19日閲覧。

参考文献

  • Jonathan Bartlett: Programming from the Ground Up. Bartlett Publishing, 2004. ISBN 0-9752838-4-7
    Also available online as PDF
  • Robert Britton: MIPS Assembly Language Programming. Prentice Hall, 2003. ISBN 0-13-142044-5
  • Paul Carter: PC Assembly Language. Free ebook, 2001.
    Website
  • Jeff Duntemann: Assembly Language Step-by-Step. Wiley, 2000. ISBN 0-471-37523-3
  • Randall Hyde: The Art of Assembly Language. No Starch Press, 2003. ISBN 1-886411-97-2
  • Peter Norton, John Socha, Peter Norton's Assembly Language Book for the IBM PC, Brady Books, NY: 1986.
  • Michael Singer, PDP-11. Assembler Language Programming and Machine Organization, John Wiley & Sons, NY: 1980.
  • Dominic Sweetman: See MIPS Run. Morgan Kaufmann Publishers, 1999. ISBN 1-55860-410-3
  • John Waldron: Introduction to RISC Assembly Language Programming. Addison Wesley, 1998. ISBN 0-201-39828-1

関連項目

外部リンク