そうでない場合、それらはどのように異なり、それらの関係は何ですか?
ありがとう、よろしく!
みなさんも同じ答えだと思います。命令セットは、プロセッサが実行または理解できるすべての命令のセットです (数学のように)。アセンブリ言語はプログラミング言語です。
あなたが尋ねているいくつかの質問に基づいて、いくつかの例を試してみましょう。そして、手元にあるコードを使って、プロセッサからプロセッサへと飛び回ります。
命令、オペコード、バイナリ、機械語など、プロセッサにロードされてデコードおよび実行されるビット/バイトに使用する任意の用語。例
0x5C0B
アセンブリ言語は、
add r12,r11
この特定のプロセッサ用。この場合、r11 = r11 + r12 を意味します。そのテキストをテキスト ファイルに追加し、r12、r11 を追加し、アセンブラ (アセンブリ言語をコンパイル/アセンブルするプログラム) を使用して、何らかの形式のバイナリにアセンブルします。他のプログラミング言語と同様に、オブジェクト ファイルを作成してそれらをリンクすることもあれば、直接バイナリに移行できることもあります。そして、アスキー形式とバイナリ形式のバイナリには多くの形式があり、その他の議論があります。
命令セットの一部ではないアセンブラーで何ができるでしょうか? それらはどのように異なりますか?まず、マクロを使用できます。
.macro add3 arg1, arg2, arg3
add \arg1,\arg3
add \arg2,\arg3
.endm
.text
add3 r10,r11,r12
マクロはインライン関数のようなもので、呼び出される関数ではなく、インラインでコードを生成します。たとえば、C マクロと同じです。したがって、それらを使用してタイピングを節約したり、何度も何度もやりたいことを抽象化したり、すべてのインスタンスに触れる必要がなく、1 か所で変更できるようにするために使用したりできます。上記の例は、基本的にこれを生成します。
add r10,r12
add r11,r12
命令セットとアセンブリ言語のもう 1 つの違いは、疑似命令です。たとえば、この特定の命令セットには、少なくともその名前ではなく、スタックからポップするためのポップ命令はありません。その理由を説明します。ただし、入力を節約し、コードで pop を使用することは許可されています。
pop r12
ポップが発生しない理由は、アドレッシング モードが柔軟であるため、ソース レジスタのアドレスからの読み取りで値をデスティネーション レジスタに置き、ソース レジスタを 1 ワードずつインクリメントすることができるからです。この命令セットのアセンブラーはどれですか
mov @r1+,r12
pop と mov の両方がオペコード 0x413C になります。
命令セットとアセンブラーの違い、命令セットの切り替えの別の例は、次のようなものです。
ldr r0,=bob
このアセンブリ言語にとっては、bob のアドレスをレジスタ 0 にロードすることを意味します。そのための命令はありません。アセンブラがそれに対して行うことは、アセンブラで手動で記述した場合に次のようになるものを生成することです。
ldr r0,ZZ123
...
ZZ123: .word bob
基本的に、実行パスではなく、その命令から到達可能な場所に、リンカーが bob のアドレスを入力するワードが作成されます。同様に、アセンブラまたはリンカによる ldr 命令は、pc 相対命令の ldr でエンコードされます。
これは、命令セットとアセンブリ言語の違いのカテゴリ全体につながります
call fun
機械語は、何が楽しいのか、どこでそれを見つけられるのかを知る方法がありません。多くのアドレッシング モードを備えたこの命令セットについて (ここで使用している命令セットの名前は、この説明とは関係ないので具体的かつ意図的に避けていることに注意してください)、場合によってはアセンブラーまたはリンカー (fun 関数がどこで終了するかによって異なります)この命令に相対的です)。
アセンブラは、その命令を pc 相対としてエンコードすることを選択する場合があります。fun 関数が call 命令より 40 バイト先にある場合、call pc+36 と同等のものでエンコードする場合があります (pc は実行時に 1 命令先行するため、4 を削除します)。これは 4 バイトの命令です)。
または、アセンブラーがどこで何が楽しいのか分からず、リンカに任せている可能性があります。その場合、リンカは関数の絶対アドレスを #0xD00D の呼び出しに似たものにすることがあります。
ロードとストアについても同じことが言えます。一部の命令セットには、near pc と far pc の相対アドレスがあり、一部の命令セットには絶対アドレスがあります。
mov bob,r1
そして、アセンブラまたはリンカ、またはその 2 つの組み合わせが残りの処理を行います。
一部の命令セットでは、アセンブラとリンカが 1 つのプログラムで同時に発生する場合があることに注意してください。最近では、オブジェクトにコンパイルしてからオブジェクトをリンクするモデルに慣れていますが、すべてのアセンブラがそのモデルに従っているわけではありません。
アセンブリ言語がいくつかのショートカットを取ることができるいくつかのケース:
hang: b hang
b .
b 2f
1:
b 1b
b 1f
1:
b 1b
2:
hang: b hang は意味があり、hang というラベルに分岐します。基本的に自分自身への分岐です。名前が示すように、これは無限ループです。しかし、このアセンブリ言語では b . 自分自身への分岐、無限ループを意味しますが、ラベルを作成して入力し、分岐する必要はありませんでした。もう 1 つのショートカットは、番号 b を使用することです。 1b は 1 後方に分岐することを意味し、アセンブラは命令の後ろまたは上にあるラベル番号 1 を探します。自己への分岐ではない b 1f は、分岐 1 前方を意味します。これは、このアセンブラーにとって完全に有効なコードです。ラベル番号 1 のコード行の前または下を検索します。このアセンブラーのアセンブリ言語プログラムで狂ったように番号 1 を再利用でき、単純な短い分岐のラベル名を発明する必要がなくなります。2 番目の b 1b は 2 番目の 1 に分岐し、自分自身への分岐です。
プロセッサを作成した会社が命令セットを定義し、マシンコードまたはオペコード、またはプロセッサがデコードおよび実行するビットとバイトに使用する用語を定義していることを理解することが重要です。多くの場合、その会社は、これらの命令、構文のアセンブリ言語を使用してドキュメントを作成します。多くの場合、その会社は、その構文を使用して、そのアセンブリ言語をコンパイル/アセンブルするためのアセンブラ プログラムを作成します。しかし、それは、その命令セット用のアセンブラーを作成することを選択した地球上の他の人がその構文を使用しなければならないという意味ではありません。これは、x86 命令セットで非常に明白です。同様に、上記の pop やマクロ構文のような疑似命令、または b 1b のようなその他のショートカットは、あるアセンブラーから別のアセンブラーに適用される必要があります。そうでない場合が非常に多く、これは ARM で見られます。たとえば、 ; のユニバーサル コメント シンボルです。代わりに @ を使用する必要がある gnu アセンブラーでは機能しません。ARM アセンブラは ; を使用します。(移植可能にするために、腕のアセンブラを ;@ で書いていることに注意してください)。たとえば、#define や /* comment */ などの C 言語をアセンブラーに配置して、アセンブラーの代わりに C コンパイラーを使用すると、それが機能します。移植性を最大限に高めるために、できる限り純粋な状態を維持することを好みますが、当然、ツールが提供する機能を使用することを選択することもできます。たとえば、#define や /* comment */ などの C 言語をアセンブラーに配置して、アセンブラーの代わりに C コンパイラーを使用すると、それが機能します。移植性を最大限に高めるために、できる限り純粋な状態を維持することを好みますが、当然、ツールが提供する機能を使用することを選択することもできます。たとえば、#define や /* comment */ などの C 言語をアセンブラーに配置して、アセンブラーの代わりに C コンパイラーを使用すると、それが機能します。移植性を最大限に高めるために、できる限り純粋な状態を維持することを好みますが、当然、ツールが提供する機能を使用することを選択することもできます。
命令セットはプロセッサが実行できるすべての命令で構成されていますが、アセンブリはこれらの命令を使用してプログラムを作成するプログラミング言語です。
言い換えると、命令セットは CPU が理解できる単なるバイトのグループですが、アセンブリはこれらの命令を組み合わせることができる言語ですが、それらを使用して有用なことは何もできません (命令をアルファベットの文字と考えてください)。 (または文字) プログラム (スピーチのようなもの) を作成します。
アセンブリ言語には命令のニーモニックが含まれますが、通常は次のようにさらに多くのものが追加されます。
編集: 命令 (それ自体) は、CPU が読み取るためにバイナリでエンコードされます。ニーモニックは、命令の名前です。たとえば、アセンブリ言語では「mov ax, 1」と書くかもしれません。これに対応する命令 (x86 の場合) は、B8 00000001 (16 進数) としてエンコードされます。
データ、マクロ、関数の名前などの定義は、実際の命令ではありません。マクロ (C などのマクロによく似ています) を使用すると、アセンブリ プロセス中に名前を定義できます。いくつかの命令が生成される可能性がありますが (多くの場合そうなるでしょう)、それらはマクロ定義自体とは別のものです。C の場合と同様に、オブジェクト ファイル内に X という名前のスペースを指定するレコードを生成するデータを定義すると、命令は直接生成されません。
アセンブリ言語は、命令セットの単なるスーパーセットではありません。オブジェクトファイル、シンボル、デバッグ情報、リンケージを生成する方法であり、このレベルでも最小限の構造化プログラミングを行う方法です。(ここで他の回答/コメントにある程度基づいています)
ほとんどのCコンパイラはアセンブリを生成し、それをアセンブラに渡してオブジェクトファイルを作成します。フラグ'-S'を指定して実行した場合のgccの出力を見ると、上記のほとんどが使用されていることがわかります。デバッグをオン('-g')にし、動的リンケージ(最近のデフォルト)を使用している場合は、命令だけに専念していない大量のアセンブリが表示されます。
質問でリンクしたアセンブリ言語に関するウィキペディアの記事を調べると、アセンブリ言語の説明と対応するオブジェクトコードを示す例が以下にあります。どちらも同じものの異なる表現です。つまり、プロセッサの命令セットからの命令です。ただし、「命令(AT&T構文)」というタイトルの列にのみアセンブリ言語が含まれています。
これがそれをより明確にすることを願っています。
すべてが「厳密な(ほとんどの場合)適切に定義されたインターフェース」を備えたレイヤードアーキテクチャにあります。
ハードウェアから始める
プロセッサに到達するまでには多くのレイヤーがあります。
レイヤー 「物理学->デバイス(電子機器)->アナログ(アンプ)->ゲート->デジタル回路->マイクロアーキテクチャ->アーキテクチャ(ISA、プロセッサ)」から始めることを意味します
ISA(Instruction Set Architecture)と呼ばれるソフトウェア部分
尊敬されるプロセッサがサポートできるすべての命令があります。これは、ISA が 1 つのプロセッサ (x86 のようなハードウェア) のみにバインドされていることを意味します。
重要なことは、なぜこの ISA が必要なのかということです。前に言ったのと同じように、それは Strict and Well Defined Interface です。プロセッサは ISA を超える命令を実行できません[Strict]
しかし、このプロセッサを使用したい人は誰でも、ISA からこれらのコマンドを使用して作業を完了できます。 [明確なインターフェース]
次に、アセンブリ、C、アセンブラ、コンパイラに来てください....
レイヤード アーキテクチャ (レイヤード アーチ) をハードウェアで使用して、1 つのプロセッサを実装します。
このレイヤード アーキテクチャの理由について詳しく読むことができます。大きな問題を段階的に処理することを容易にします。
ここで私たちが望むものと同じですか?私たちの目標は何ですか?
ユーザーがこのプロセッサを簡単に使用できるようにしたい。ここでユーザーはプログラマーです。
今プログラマーの難しさを見てください。
プログラマは、バイナリ形式のプロセッサのすべての命令を覚えることができますか? また、プロセッサは次のアプリケーションで Intel から IBM に変更される可能性があります (現時点ではバージョン固有ではありません)。
アセンブラーもレイヤーであり、2 つのインターフェイスがあります。コンパイラと同じです。
例: C でコードを書きます。プロセッサはこのコードを理解できません。バイナリ形式で記述され、ISA で与えられた命令で定義されているものは何でも理解します。しかし、ISA では命令にプログラムを書き込む (維持する) ことは困難です。
1) それで、ユーザーは C でコードを書きます。このコードは C コンパイラーが理解します。ユーザーは、C で指定された構文のみを使用するように制限されているためです。これは、C コンパイラーが一方の端で標準的で明確に定義されたインターフェイスをユーザーに提供することを意味します。もう1つは、ISA命令または「アセンブラ」と呼ばれる別のインターフェイスを直接使用できます。
2) アセンブラを使用している場合、コンパイラはすべての C コードをアセンブラによって指定された構文に変換します。そして、アセンブラーがコンパイラーに提供する構文は、アセンブリー言語と呼ばれます。また、明確に定義されたインターフェイスであり、誰でもそれを使用してアセンブリ言語でプログラミングできます。もう一方の端では、アセンブラーがすべての構文 (ニーモニック | ディレクティブ、ISA には存在しないもの) を ISA のバイナリ コード命令に変換します。
ここにこの翻訳の例があります。
このファイルの 1 行は"Machine: Advanced Micro Devices X86-64"で、ISA とアセンブラーを使用しているプロセッサに関する情報を提供しています。そして、C プログラマーはこれを認識せず、C で自由にコーディングできます。それが「適切に定義されたインターフェイス」の利点です。
見るだけで比較する
hello.c (C プログラム)
hello.asm2bin (オブジェクト ファイル テーブル: ニーモニックとバイナリ命令の直接マッピング)
hello.asm2bin_exe (バイナリ ファイル テーブル: リンク後の追加マッピング)
これらのファイルに「Disassembly of section ..」という行が表示さ れます。これは、アセンブラが行うことから、アセンブリ言語から ISA 命令 (ビット パターン) をアセンブルするためです。ここでは、最初に ISA 命令を見て、次にニーモニックに逆アセンブルしています。
すべてのファイルはこのリンクにあります [ダウンロードして開く]
https://www.dropbox.com/sh/v2moak4ztvs5vb7/AABRTxl7KQlqU2EkkMkKssqYa?dl=0