読み方:あっせんぶりー
アセンブリとは、Microsoft .NET Frameworkの環境における、アプリケーションなどの管理単位となるコンパイル済みのコード群のことである。
アセンブリは、Windowsにおける実行ファイルであるdll、および、exeファイルの書式であるPEフォーマットに従うもので、その中に配置、バージョン、セキュリティに関する情報やその他のメタデータを含んでいる。
.NET Framework環境では、アプリケーションはコンパイル後にCIL(Common Intermediate Language)と呼ばれる中間言語にコンパイルされ、ランタイム環境であるCLR(Common Language Runtime)が持つJITコンパイラ(Just In Time Compiler)を用いて機械語に変換され、VES(Virtual Execution System、仮想実行システム)で実行される。
開発者は、アセンブリを作成する際、そのアセンブリに開発者をユニークに識別する署名を付与することができる。この場合、ファイルが例え上書き、あるいは、変更されたとしても、正しい組み合わせかどうかを適切に検出することができる。また、利用するライブラリのバージョンの違いによって生じる不具合(いわゆる「DLL地獄」)を解消することができる。
アセンブリには、前提とするCLRのバージョンにより、バージョン1.1、2.0などの区別があるため、インストールにあたり、CLRのバージョンとの整合性を意識する必要がある。
構文<SerializableAttribute> _ <ClassInterfaceAttribute(ClassInterfaceType.None)> _ <ComVisibleAttribute(True)> _ Public Class Assembly Implements _Assembly, IEvidenceFactory, ICustomAttributeProvider, ISerializable
[SerializableAttribute] [ClassInterfaceAttribute(ClassInterfaceType.None)] [ComVisibleAttribute(true)] public class Assembly : _Assembly, IEvidenceFactory, ICustomAttributeProvider, ISerializable
[SerializableAttribute] [ClassInterfaceAttribute(ClassInterfaceType::None)] [ComVisibleAttribute(true)] public ref class Assembly : _Assembly, IEvidenceFactory, ICustomAttributeProvider, ISerializable
解説アセンブリは、インフラストラクチャを用意します。このインフラストラクチャによって、Runtime がアプリケーションの内容を完全に理解し、アプリケーションで定義されるバージョン管理と依存関係の規則を適用できます。これらは、バージョン管理の問題を解決し、Runtime アプリケーションの配置を単純化するために重要な概念です。
使用例アセンブリ内の各メソッドについて、メソッド シグネチャを列挙するコード例を次に示します。
' LoadInvoke loads MyAssembly.dll and lists the method ' information for each method. After compiling this class, ' run LoadInvoke.exe with the DisplayName for the assembly, ' as shown here: ' LoadInvoke MyAssembly Imports System Imports System.Reflection Imports System.Security.Permissions Public Class LoadInvoke <PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _ Public Shared Sub Main(ByVal args() As String) Dim a As [Assembly] = [Assembly].Load(args(0)) Dim mytypes As Type() = a.GetTypes() Dim flags As BindingFlags = BindingFlags.NonPublic Or BindingFlags.Public Or BindingFlags.Static Or _ BindingFlags.Instance Or BindingFlags.DeclaredOnly Dim t As Type For Each t In mytypes Dim mi As MethodInfo() = t.GetMethods(flags) Dim obj As [Object] = Activator.CreateInstance(t) Dim m As MethodInfo For Each m In mi ' Instead of invoking the methods, ' it's safer to initially just list them. Console.WriteLine(m) Next m Next t End Sub End Class
// LoadInvoke loads MyAssembly.dll and lists the method // information for each method. After compiling this class, // run LoadInvoke.exe with the DisplayName for the assembly, // as shown here: // LoadInvoke MyAssembly using System; using System.Reflection; using System.Security.Permissions; public class LoadInvoke { [PermissionSetAttribute(SecurityAction.Demand, Name="FullTrust")] public static void Main(string[] args) { Assembly a = Assembly.Load(args[0]); Type[] mytypes = a.GetTypes(); BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly); foreach(Type t in mytypes) { MethodInfo[] mi = t.GetMethods(flags); Object obj = Activator.CreateInstance(t); foreach(MethodInfo m in mi) { // Instead of invoking the methods, // it's safer to initially just list them. Console.WriteLine(m); } } } }
' Use this class with the LoadInvoke program. ' Compile this class using vbc /t:library MyAssembly.vb ' to obtain MyAssembly.dll. Imports System Imports Microsoft.VisualBasic Public Class MyAssembly Public Sub MyMethod1() Console.WriteLine("Invoking MyAssembly.MyMethod1") End Sub 'MyMethod1 End Class 'MyAssembly
// Use this class with the LoadInvoke program. // Compile this class using "csc /t:library MyAssembly.cs" // to build MyAssembly.dll. using System; public class MyAssembly { public void MyMethod1() { Console.WriteLine("This is MyMethod1"); } public void MyMethod2() { Console.WriteLine("This is MyMethod2"); } public void MyMethod3() { Console.WriteLine("This is MyMethod3"); } }
継承階層
スレッド セーフ
プラットフォームWindows 98, Windows 2000 SP4, Windows CE, Windows Millennium Edition, Windows Mobile for Pocket PC, Windows Mobile for Smartphone, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition
開発プラットフォームの中には、.NET Framework によってサポートされていないバージョンがあります。サポートされているバージョンについては、「システム要件」を参照してください。
バージョン情報
参照
パブリック プロパティ| 名前 | 説明 | |
|---|---|---|
| CodeBase | アセンブリの場所を初めに指定されたとおりに取得します。たとえば、AssemblyName オブジェクトなどがあります。 |
| EntryPoint | このアセンブリのエントリ ポイントを取得します。 |
| EscapedCodeBase | コードベースを表す URI を、エスケープ文字も含めて取得します。 |
| Evidence | このアセンブリの証拠を取得します。 |
| GlobalAssemblyCache | アセンブリがグローバル アセンブリ キャッシュから読み込まれたかどうかを示す値を取得します。 |
| HostContext | アセンブリの読み込みに使用したホスト コンテキストを取得します。 |
| ImageRuntimeVersion | マニフェストを格納しているファイルに保存された共通言語ランタイム (CLR: common language runtime) のバージョンを表す文字列を取得します。 |
| Location | マニフェストを格納している読み込み済みファイルのパスまたは UNC 位置を取得します。 |
| ReflectionOnly | このアセンブリがリフレクションのみのコンテキストに読み込まれたかどうかを示す Boolean 値を取得します。 |
参照
パブリック メソッド
プロテクト メソッド| 名前 | 説明 | |
|---|---|---|
| Finalize | Object がガベージ コレクションにより収集される前に、その Object がリソースを解放し、その他のクリーンアップ操作を実行できるようにします。 ( Object から継承されます。) |
| MemberwiseClone | 現在の Object の簡易コピーを作成します。 ( Object から継承されます。) |
明示的インターフェイスの実装
参照Assembly を定義します。このアセンブリは再利用でき、バージョン管理可能で自己記述型の共通言語ランタイム アプリケーションのビルド ブロックです。
Assembly データ型で公開されるメンバを以下の表に示します。
パブリック プロパティ| 名前 | 説明 | |
|---|---|---|
| CodeBase | アセンブリの場所を初めに指定されたとおりに取得します。たとえば、AssemblyName オブジェクトなどがあります。 |
| EntryPoint | このアセンブリのエントリ ポイントを取得します。 |
| EscapedCodeBase | コードベースを表す URI を、エスケープ文字も含めて取得します。 |
| Evidence | このアセンブリの証拠を取得します。 |
| GlobalAssemblyCache | アセンブリがグローバル アセンブリ キャッシュから読み込まれたかどうかを示す値を取得します。 |
| HostContext | アセンブリの読み込みに使用したホスト コンテキストを取得します。 |
| ImageRuntimeVersion | マニフェストを格納しているファイルに保存された共通言語ランタイム (CLR: common language runtime) のバージョンを表す文字列を取得します。 |
| Location | マニフェストを格納している読み込み済みファイルのパスまたは UNC 位置を取得します。 |
| ReflectionOnly | このアセンブリがリフレクションのみのコンテキストに読み込まれたかどうかを示す Boolean 値を取得します。 |
パブリック メソッド
プロテクト メソッド| 名前 | 説明 | |
|---|---|---|
| Finalize | Object がガベージ コレクションにより収集される前に、その Object がリソースを解放し、その他のクリーンアップ操作を実行できるようにします。 (Object から継承されます。) |
| MemberwiseClone | 現在の Object の簡易コピーを作成します。 (Object から継承されます。) |
パブリック イベント
明示的インターフェイスの実装
参照
構文<InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)> _ <ComVisibleAttribute(True)> _ <GuidAttribute("17156360-2f1a-384a-bc52-fde93c215c5b")> _ <CLSCompliantAttribute(False)> _ Public Interface _Assembly
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)] [ComVisibleAttribute(true)] [GuidAttribute("17156360-2f1a-384a-bc52-fde93c215c5b")] [CLSCompliantAttribute(false)] public interface _Assembly
[InterfaceTypeAttribute(ComInterfaceType::InterfaceIsDual)] [ComVisibleAttribute(true)] [GuidAttribute(L"17156360-2f1a-384a-bc52-fde93c215c5b")] [CLSCompliantAttribute(false)] public interface class _Assembly
解説このインターフェイスは、アンマネージ コードからマネージ クラスにアクセスするためのインターフェイスであるため、マネージ コードからは呼び出さないでください。
このインターフェイスでは、アンマネージ COM オブジェクトでアクセス可能な System.Reflection.Assembly クラス メンバの vtable の順序が保持されます。
プラットフォームWindows 98, Windows 2000 SP4, Windows Millennium Edition, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition
開発プラットフォームの中には、.NET Framework によってサポートされていないバージョンがあります。サポートされているバージョンについては、「システム要件」を参照してください。
バージョン情報
参照
パブリック プロパティ| 名前 | 説明 | |
|---|---|---|
| CodeBase | COM オブジェクトに、Assembly.CodeBase プロパティへのバージョンに依存しないアクセスが用意されています。 |
| EntryPoint | COM オブジェクトに、EntryPoint プロパティへのバージョンに依存しないアクセスが用意されています。 |
| EscapedCodeBase | COM オブジェクトに、EscapedCodeBase プロパティへのバージョンに依存しないアクセスが用意されています。 |
| Evidence | COM オブジェクトに、Evidence プロパティへのバージョンに依存しないアクセスが用意されています。 |
| FullName | COM オブジェクトに、FullName プロパティへのバージョンに依存しないアクセスが用意されています。 |
| GlobalAssemblyCache | COM オブジェクトに、GlobalAssemblyCache プロパティへのバージョンに依存しないアクセスが用意されています。 |
| Location | COM オブジェクトに、Location プロパティへのバージョンに依存しないアクセスが用意されています。 |
参照
パブリック メソッド
参照System.Reflection.Assembly クラスのパブリック メンバをアンマネージ コードに公開します。
_Assembly データ型で公開されるメンバを以下の表に示します。
パブリック プロパティ| 名前 | 説明 | |
|---|---|---|
| CodeBase | COM オブジェクトに、Assembly.CodeBase プロパティへのバージョンに依存しないアクセスが用意されています。 |
| EntryPoint | COM オブジェクトに、EntryPoint プロパティへのバージョンに依存しないアクセスが用意されています。 |
| EscapedCodeBase | COM オブジェクトに、EscapedCodeBase プロパティへのバージョンに依存しないアクセスが用意されています。 |
| Evidence | COM オブジェクトに、Evidence プロパティへのバージョンに依存しないアクセスが用意されています。 |
| FullName | COM オブジェクトに、FullName プロパティへのバージョンに依存しないアクセスが用意されています。 |
| GlobalAssemblyCache | COM オブジェクトに、GlobalAssemblyCache プロパティへのバージョンに依存しないアクセスが用意されています。 |
| Location | COM オブジェクトに、Location プロパティへのバージョンに依存しないアクセスが用意されています。 |
パブリック メソッド
パブリック イベント
参照2つ以上の部品を締結部品(ボルトナット、クリップ、ファスナーなど)、溶接、かしめなどで一緒に組み付けること。アッシー部品同士を組み付けて、さらに大きなアッシーにすることもある。狙いは作業の平準化、単純化などによる品質の安定、コスト低減。
(assembly から転送)
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2026/02/18 21:54 UTC 版)
アセンブリ言語(アセンブリげんご、英: assembly language)とは、特定のコンピュータのCPUが実行する機械語命令を、人間が読み書き可能な記号(ニーモニック)で表現した低水準言語の総称である[1]。
各命令は通常、対象となる命令セットとほぼ一対一で対応し、アセンブラと呼ばれる翻訳プログラムによって機械語へ変換される。コンピュータのハードウェア構造に強く依存する点を特徴とする。
アセンブラ(英: Assembler)またはアセンブラ言語(英: Assembler Language)とも呼ばれる[注 1][2]。
プロセッサは機械語プログラムを直接読み取り実行する。しかし人間にとってビット列は直観的に理解しづらいため、機械語コーディングは容易でない。これを解決するために、ビット列に対応する文字列命令(ニーモニック)を利用するプログラミング言語の総称がアセンブリ言語である[1]。
アセンブリ言語を用いることで、機械語相当の低水準なコードをより直観的に記述できる。高度なアセンブリ言語ではアセンブラに対する命令(疑似命令)やマクロを用いて、より抽象的な記述が可能である[注 2]。パイプライン処理などを最適化するために命令順序を入れ替えたり、ラベルの位置関係によってアドレッシングモードを最適化するアセンブラもあり、必ずしもソーステキストの記述とアセンブルの結果が直接対応するとは限らない。
アセンブリ言語は機械語と強く結びついているため、各プロセッサ向けに仕様の異なる様々な(具体的な)アセンブリ言語が存在する(「アセンブリ言語」は総称である)。同じ命令セットに対しても複数のアセンブリ言語が存在しうる(例: GNUアセンブラのgasのインテルプロセッサ用)。
アセンブリ言語の基本文法として、1つの命令は1つのニーモニックと0個以上のオペランドからなる。プログラム全体はニーモニック/オペランド列、ディレクティブや擬似命令と呼ばれるメタな文、コメント、データで構成されている。通常の文はオペコードのニーモニックで始まり、パラメータ(データ、引数)のリストがそれに続く[3]。多くのアセンブリ言語はオペランドのアドレスや定数をラベル・シンボルで記述できハードコーディングを避けられる。
アセンブラの開発者によって用語の使い方に大きな差異があり、文の分類などが異なる。例えば、マシンのニーモニックや拡張ニーモニック以外は全て擬似命令と呼ぶ場合もある。典型的なアセンブリ言語は、プログラムの操作の定義に使われる命令文をニーモニック、データセクション、アセンブリディレクティブの3種類に分類する。
ニーモニック(英: mnemonic)は処理内容に応じて各機械語命令に与えられた文字列・命令語である[4]。機械語のオペコードに相当する。
ビット列である機械語はその処理が直観的にわからないため、機械語コーディングは容易でない。人間がより容易に機械語と同等なコードを書くため、ビット列を意味ある文字列で表現するニーモニックが発明された[4]。例えばx64機械語 0x05 は「整数の加算」を意味するのでニーモニック ADD を対応させる。個々の機械語命令には少なくとも1つのニーモニックが対応する。
拡張ニーモニックは命令の特殊な用途をサポートするのに使われることが多く、本来の命令の名称からはその用途が連想できないときに使うことが多い。例えば、多くの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と呼んでいる[5]。
命令は一般に1個の「オペコード」と0個以上の「オペランド」で構成される。多くの命令は1個または2個の値を参照する。オペランドには即値(命令内に置かれる値)、レジスタ(暗黙のうちに使用される場合もある)、記憶装置内のデータの位置を示すアドレスなどがある。「拡張ニーモニック」はオペコードと特定オペランドの組合せを表すのに使われることが多い。例えば、System/360では、BC命令にマスク15を組み合わせたものがB、BC命令にマスク0を組み合わせたものがNOPという拡張ニーモニックで表される。オペランドの順序(例: ソースとディスティネーションの前後)は言語に依る。
オペランド(英: operand、被演算子)は命令の対象・引数である。1つの命令では、ニーモニックに続き0個以上のオペランドが記述される。オペランドにはソースとデスティネーションの二種類があり、データとして読み取られるのがソースで、オペコードで示された命令の実行結果が格納されるのがデスティネーションである。ソースには定数・レジスタ・メモリのいずれか、デスティネーションにはレジスタ・メモリのいずれかを指定する。
データと変数を保持するデータ要素を定義するのに使われる命令文がある。データの型、長さ、境界(アライメント)を定義する。また、そのデータがプログラム外部(別ファイルでアセンブルされたプログラム)からも利用可能なのか、それともデータセクションを定義したプログラム内でのみ使用可能なのかも定義できる。一部のアセンブラはこれを擬似命令に分類している。
アセンブリディレクティブは、擬似命令とも呼ばれ、アセンブラがアセンブリ実施中に実行すべき命令となっている[6]。プログラマが入力するパラメータによって、異なった形でアセンブルが行われるよう指示することができる。また、プログラムの見た目を操作して、可読性と保守性を向上させるのにも使われる。例えば、記憶装置の領域を予約し、その初期内容を指定するディレクティブなどがある。ディレクティブの名称はドットで始まることが多く、それによって通常のニーモニックと区別している。
擬似オペコード(pseudo-opcode)と言った場合、オブジェクトコードを実際に生成するディレクティブのみを指すこともある[7]。
シンボリックアセンブラでは、任意の名前(ラベルまたはシンボル)とメモリ位置を対応付けることができる。通常、定数や変数に名前をつけることができ、命令文ではそれらの位置を名前で参照できる。実行コードではサブルーチンのエントリポイントと名前を関連付け、サブルーチンを名前で呼び出すことができる。サブルーチン内では、分岐命令の分岐先をラベルで示すことができる。一部のアセンブラは「ローカルシンボル」をサポートしており、通常のシンボルとは語彙的に区別する(例えば、"10$"を分岐先に使用する、など)。
一部のアセンブラは柔軟なシンボル管理を提供しており、複数の名前空間を管理したり、データ構造内のオフセットを自動的に計算したり、リテラル値やアセンブラが実施した単純な計算結果を参照するラベルを割り当てたりすることができる。ラベルは定数や変数をリロケータブルなアドレスで初期化するのにも使える。
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]。
アセンブリ言語は低水準プログラミング言語であり、C言語などの高級言語より抽象度が低い。すなわち言語機能(構文や型)が少ない。次の表は「基本的なアセンブリ言語」と高級言語の間にある言語機能差である。
| アセンブラ | 高級言語 | |
|---|---|---|
| レジスタ | ✔ | - |
| ジャンプ命令 | ✔ | △[10] |
| 制御構造 | - | ✔ |
| 構造体 | - | ✔ |
| 関数 | - | ✔ |
| コメント | ✔ | ✔ |
この差はあくまで言語機能の差である。「高級言語でのみ可能、アセンブリ言語では不可」という意味ではない。例えばアセンブリ言語に関数構文は存在しないが関数に相当するパターンが存在する(関数プロローグ・エピローグ)。より正確な言い方をすれば、アセンブラで頻出するパターンを1つの機能として言語仕様に組み込んで抽象度を上げていった言語が高級言語である。
より抽象化され少ないコード量でアセンブラを書くために様々な高水準文法がアセンブリ言語に導入されてきた。現在では高水準化のメインストリームは高級言語に移った一方[11]、目的に応じてアセンブリ言語を選択するユーザー向けに高機能なアセンブリ言語の開発も続いている[12]。
アセンブリ言語においてもマクロが利用される。一般的なマクロと同様、高度なアセンブラマクロでは制御構文導入・引数展開・ユーザー定義マクロ適用などが可能である。文字列であるオペコード・ニーモニックはマクロの対象となるため、これを利用して疑似ニーモニックによる記述も可能になる。
例えば、一部のZ80用アセンブラでは、ld hl,bc というマクロ命令を ld l,c と ld h,b という2命令に展開する[13]。メインフレームの時代には、マクロは特定顧客の大規模ソフトウェアシステムのカスタマイズや、メーカーのオペレーティングシステムを顧客の要望に合わせた特注版にするのに使われていた。IBMの VM/CMS、リアルタイムトランザクション処理用アドオン、CICS、ACP/TPF[14]などで使われてきた。
構造化プログラミングの要素を取り入れたアセンブラもある。最初期には "Concept-14 macro set" がSystem/360のマクロアセンブラにIF/ELSE/ENDIFなどの制御構造を導入した[15][16]。また8080/Z80プロセッサ向けのA-naturalではブロック構造や命令実行順序の制御が採用された。
また構造化プログラミングとは若干異なるが、キャリーラボは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
アセンブル(英: assemble)はアセンブリ言語で書かれたプログラムから機械語で書かれたオブジェクトコードへの変換である。具体的には、ニーモニックをオペコードに変換しシンボル名をメモリ位置や他の実体に変換する[6]。
アセンブルは比較的単純な規則からなるため、人の手でも実行できる(ハンドアセンブル)。単純な作業を効率良くミス無く行うのはプログラムの得意分野であり、そのようなソフトウェアが開発された。このアセンブリをおこなうプログラムをアセンブラ(英: assembler)という。初期にはアセンブリプログラムとも呼ばれた[17]。
シンボル名による参照の利用はアセンブラの重要な機能であり、面倒な計算やプログラム修正に伴うアドレスの更新の手間を省くことができる。また、オブジェクトコードを生成する際、ローダ用情報も併せて生成するアセンブラもある[18]。マクロを含むアセンブリ言語に対応している場合、処理系にはm4のような汎用プロセッサあるいはプロセッサ内蔵アセンブラ(マクロアセンブラ)が利用される[19]。ポリモーフィズム、継承[8]などをもつ高水準アセンブリ言語に対応したアセンブラは高水準アセンブラと呼ばれる[20]。
動作プラットフォーム以外のターゲットプラットフォームを選択できるアセンブラはクロスアセンブラとも呼ばれる(参考: クロスコンパイラ)。メタアセンブラは、アセンブリ言語の文法や意味論を記述したものを入力とし、その言語のためのアセンブラを出力するプログラムである[21]。
逆方向の変換、すなわちオブジェクトコードのアセンブリ言語化をおこなうプログラムを逆アセンブラという。
アセンブラは様々な観点から分類できる。パス回数(アセンブル時のソースファイル走査回数)の観点ではワンパスアセンブラとマルチパスアセンブラに分類できる。
どちらの場合も、アセンブラは最初のパスで各命令のサイズを確定させる必要があり、それによって後に出現するシンボルのアドレスを計算する。命令のサイズは後から定義されるオペランドの型や距離に依存することがあるため、アセンブラは最初のパスでは悲観的な見積もりをし、必要に応じてその後のパスまたは errata にて1つ以上のNOP命令(何もしない命令)を挿入してすき間を埋める必要がある。最適化を行うアセンブラでは、最初の悲観的コードをその後のパスで稠密なコードに書き換えてアドレスの再計算を行うことがある。
もともとワンパスアセンブラは高速であるためよく使われていた。マルチパス動作をするには、磁気テープを巻き戻したりパンチカードのデッキをセットし直して読み込む必要があったためである。現代のコンピュータではマルチパスであってもそのような遅延は生じない。マルチパスアセンブラは errata がないため、リンク処理(アセンブラが直接実行コードを生成する場合はローダの処理)が高速化される[22]。
Unix系システムでは、アセンブラをasと呼ぶのが一般的だが、実体はそれぞれのOSで異なる。GNUアセンブラを使っているものが多い。
同じ系統のプロセッサであっても、複数のアセンブリ言語の方言が存在する。アセンブラによっては他の方言のアセンブリ言語も使用可能な場合がある。例えば、TASMはMASM用コードを入力として受け付け可能だが、逆は不可能である。FASMとNASMは文法がほぼ同じだが、サポートしているマクロが異なるため、相互の翻訳は困難である。いずれも基本機能は同じだが、追加機能に差異がある[23]。
アセンブリ言語は、ごく単純なものまで含めれば、プログラム内蔵方式のコンピュータの最初期の1940年代から存在している。世界で最初に実用的に稼働したノイマン型電子計算機とされるEDSAC(1949年)のinitial orders(現代の用語ではブートローダーに相当するもの)は、テープにパンチされた十進によるアドレスを、内部表現の二進に変換するなどの機能を持っていた(命令については、「1文字のニーモニック」に見えるかもしれないが、それは実際には同機の機械語そのものである)[24]。ナサニエル・ロチェスターは1954年に IBM 701 用アセンブラを書いている。1955年、Stan PoleyがIBM 650用言語アセンブSOAP(Symbolic Optimal Assembly Program)を開発した[25]。
コンピュータの歴史の初期には、このような、プログラムによって機械語プログラムを生成することを自動プログラミングと呼んだ。
ドナルド・ギリースは、まだ発明されていなかったアセンブラを開発中に、フォン・ノイマンから開発を即座に止めるように言われた、という1950年代初期ならではの逸話がある。当時は、人間が手作業でもできるような瑣末な仕事をコンピュータにさせるような時代が来るとは考えられておらず、単に時間の無駄だとノイマンは考えたのである。
歴史的には多数のプログラム(OSやアプリケーション)がアセンブリ言語だけで書かれてきた。ALGOLの方言であるESPOLで書かれた Burroughs MCP(1961年)が登場するまで、オペレーティングシステムはアセンブリ言語で書くのが普通だった。IBMのメインフレーム用ソフトウェアの多くはアセンブリ言語で書かれていた。COBOL、FORTRAN、PL/Iなどが取って代わっていったが、1990年代になってもアセンブリ言語のコードベースを保守し続けていた大企業も少なくない。
初期のマイクロコンピュータでも同様に広く用いられた。これは、リソースの制約が厳しく、メモリやディスプレイのアーキテクチャが特殊だったからである。また、マイクロコンピュータ向けの高水準言語のコンパイラがなかったという面も重要である。また、初期のマイクロコンピュータのユーザは趣味としての使用が主であり、何でも自前で作るという精神もそれに影響していたと見られる。
1980年代から1990年代にかけて、ホームコンピュータ(ZX Spectrum、コモドール64、Amiga、Atari ST など)でもアセンブリ言語がよく使われていた。というのもそれらのBASICは性能が低く、ハードウェアの全機能を利用できないことが多かったためである。例えば、Amigaにはフリーウェアのアセンブリ言語統合開発環境 ASM-One assembler があり、Microsoft Visual Studioに匹敵する機能を備えていた。
Don French が開発した VIC-20 用アセンブラは 1,639 バイトという小ささで、世界一小さいアセンブラと言われている。アドレスをシンボルで表現でき、各種アドレス計算(四則演算、AND、OR、冪乗など)が可能だった[26]。
1980年代のビジネスソフトでは、例えば表計算ソフト Lotus 1-2-3 などはアセンブリ言語で書かれていた。日本では松などが該当[27]する。
1990年代に入っても、コンシューマーゲームの多くはアセンブリ言語でプログラムが書かれていた。しかしゲーム内容が複雑化し、プログラムの規模が増大するにつれて、アセンブラでは開発が困難となり、高水準言語による開発が主流となっていった。例えばPlayStationではGCCが公式のSDKに含まれていて、標準の開発言語はC言語であった[28][29]。この時代のゲーム機は3次元コンピュータグラフィックスの積極的な導入が始まっており、ハードウェア性能も向上したことから、C言語による開発も十分可能となったが、コンパイラの最適化能力が未成熟だったこともあいまって、ハードウェア性能を最大限引き出すにはアセンブリ言語を駆使した手動最適化や細かなチューニングが必要となることも多かった。セガサターンの最高性能を引き出してプレイステーションに対抗するには、アセンブリ言語を使うしかなかったと述べていた業界関係者もいた[30]。ただし一方で、ファミリーコンピュータ時代すでにメタルスレイダーグローリーやスーパーファミコンのMOTHER 2・シムシティ[31]、プレイステーションのクラッシュ・バンディクーで[32]、開発の一部にLISPが使われていたという話もあり、当時のコンシューマーゲームの分野ではアセンブリ言語やC言語が全てだったというわけではない。
2000年代初頭、マイクロソフトは原始的なプログラマブルシェーダーに対応したDirectX(Direct3D)8.0をリリースした。このDirect3D 8.0におけるシェーダープログラムは、グラフィックスハードウェアに依存しない中間言語(バイトコード)を出力することのできるアセンブリ言語(シェーダーアセンブラ)を使用して記述するものだった。2001年には世界で初めてプログラマブルシェーダーに対応したコンシューマーゲーム機として初代Xboxが登場したが、このXboxに搭載されていたグラフィックスAPIもDirect3D 8.x相当のカスタマイズ版[33]であり、CPU上で実行するホストプログラム(ゲームアプリケーション本体のコード)はC++を使って記述する一方、GPU上で実行するシェーダープログラムの記述にはアセンブラを使用していた。のちにHLSLやCg(C for Graphics)といった高水準シェーディング言語が開発され、HLSLに対応したDirect3D 9.0以降はシェーダープログラムも高水準言語を利用して記述するようになった。Direct3D 10のシェーダーモデル4.0以降は、シェーダーアセンブラではなくHLSLの使用が必須となっている[34]。
現在の最適化コンパイラは人手で書かれたアセンブリ言語のコードと同等の性能を発揮すると言われている[35](例外もある[36][37][38])。最近[いつ?]のプロセッサやメモリサブシステムは複雑化してきたため、コンパイラでもアセンブリ言語でも効果的な最適化がますます困難になってきている[39][40]。さらにプロセッサが高性能化し律速が入出力やページングへ移ることで、コーディングが性能向上に貢献するケースは以前より少なくなっている。
一方C++やC#のような、Cよりもさらに高水準の言語が主流になってからも、コンパイラが出力したアセンブリコードを解析して最適化やチューニングの余地を探るといった手法は一般的に行なわれている[41]。
低水準言語であるアセンブラはC言語などの高級言語と異なる領域で利用される。
アセンブラを用いる目的として以下が挙げられる。
アセンブリ言語が用いられる事例として以下が挙げられる。
EXPORT_SYMBOL(ないしはその派生)[43]へ与える。このマクロは、インラインアセンブリを用いてオブジェクトファイルのセクション.export_symbolへシンボルの情報を追加し、モジュールローダがシンボル解決にて使用できるようにする。マクロの内容はCPUアーキテクチャには依存せず、その定義もCPUアーキテクチャに依存しないヘッダファイル(include/linux/export.h)[注 3]にあるが、C言語を含め高級言語のみでの実装が難しく、アセンブリが適している。[注 4]なお一方で、 最近[いつ?]のコンピュータの命令セットはその多くはどれも似ている。したがって、どれか1つのアセンブリ言語を学ぶだけで、基本概念、どんなときにアセンブリ言語を使用するのが適しているか、高水準言語から効率的な実行コードを生成する方法をある程度は学習できる[44]。
goto文が存在する言語もあるが、限定利用が推奨される