x86 は、アセンブリを学習する可能性のある他のほとんどすべての「通常の」CPU と同様に、レジスタ マシン1です。プログラムできるものを設計する方法は他にもあります (たとえば、メモリ内の論理的な「テープ」に沿って動くチューリング マシンやライフ ゲーム)。パフォーマンス。
https://www.realworldtech.com/architecture-basics/2/は、アキュムレータやスタック マシンなど、現在は廃止されている可能性のある代替手段をカバーしています。ロードストアまたはレジスタメモリのいずれかになることができるx86のようなCISCは省略されていますが。x86 命令は、実際にはreg,mem にすることができます。レグ、レグ; またはmem、reg。(または直接のソースを使用します。)
脚注 1:レジスタ マシンと呼ばれる計算の抽象モデルは、レジスタとメモリを区別しません。レジスタと呼ばれるものは、実際のコンピューターのメモリに似ています。ここで言う「レジスタ マシン」とは、 1 つのアキュムレータやスタック マシンなどではなく、複数の汎用レジスタを備えたマシンを意味します。ほとんどの x86 命令には 2 つの明示的なオペランドがあります (ただし、状況によって異なります))、そのうちの 1 つまでメモリにすることができます。6502 のような 1 つのアキュムレータ レジスタへの計算しか実際には実行できないマイクロコントローラでさえ、ほとんどの場合、他のレジスタ (ポインタやインデックスなど) を持っています。アキュムレータにさまざまなものをリロードし、直接使用できる場所に配列インデックスやループカウンターを保持することさえできません。
x86 はレジスターを使用するように設計されているため、パフォーマンスを気にしたくなくても、レジスターを完全に回避することはできません。
現在の x86 CPU は、メモリ位置よりも多くのレジスタをクロック サイクルごとに読み書きできます。
たとえば、Intel Skylake は、サイクルごとに 32KiB 8 ウェイ連想 L1D キャッシュとの間で 2 つのロードと 1 つのストアを実行できますが (最良の場合)、クロックごとに 10 個以上のレジスタを読み取り、3 または 4 個 (および EFLAGS) を書き込むことができます。
レジスタ ファイルと同じ数の読み取り/書き込みポートを備えた L1D キャッシュを構築すると、(トランジスタの数/面積と消費電力の点で) 非常にコストがかかります。x86が同じパフォーマンスでレジスタを使用する方法でメモリを使用できるものを構築することは、おそらく物理的に不可能です。
また、レジスタに書き込み、再度読み取る場合、CPU がこれを検出し、結果を 1 つの実行ユニットの出力から別の実行ユニットの入力に直接転送し、ライトバック ステージをバイパスするため、基本的にレイテンシはゼロです。( https://en.wikipedia.org/wiki/Classic_RISC_pipeline#Solution_A._Bypassingを参照)。
実行ユニット間のこれらの結果転送接続は、「バイパス ネットワーク」または「転送ネットワーク」と呼ばれます。CPU がレジスタ設計のためにこれを行う方が、すべてをメモリに入れてバックアウトする必要がある場合よりもはるかに簡単です。CPU は、32 ビットまたは 64 ビットのアドレスではなく、3 ~ 5 ビットのレジスタ番号をチェックするだけで、1 つの命令の出力が別の操作の入力としてすぐに必要な場合を検出できます。(そして、これらのレジスタ番号はマシンコードにハードコーディングされているため、すぐに利用できます。)
他の人が述べたように、レジスタのアドレス指定に 3 または 4 ビットを使用すると、すべての命令に絶対アドレスがある場合よりもマシンコード形式がはるかにコンパクトになります。
https://en.wikipedia.org/wiki/Memory_hierarchyも参照してください: レジスタは、直接絶対アドレス指定のみがサポートされているメイン メモリとは別の、小さくて高速な固定サイズのメモリ空間と考えることができます。(レジスタを「インデックス」することはできません。1 つのレジスタに整数が指定されている場合、1つの insn で th レジスタN
の内容を取得することはできません。)N
レジスタは単一の CPU コアに対してもプライベートであるため、順不同で実行すると、必要に応じて何でも実行できます。メモリを使用すると、他の CPU コアから見えるようになる順序を気にする必要があります。
固定数のレジスタを持つことは、CPU が順不同で実行するためにレジスタの名前を変更できるようにするための一部です。命令がデコードされたときにレジスタ番号をすぐに利用できるようにすることで、これも簡単になります。まだ知られていないレジスタへの読み取りまたは書き込みは決してありません。
Agner の命令表とは異なり、Haswell で mulss が 3 サイクルしかかからないのはなぜですか?を参照してください。(複数のアキュムレータを使用した FP ループのアンロール)レジスタの名前変更の説明、および特定の例 (後の質問の編集/私の回答の後半の部分は、複数のアキュムレータを使用したアンロールによるスピードアップを示し、同じものを再利用しても FMA レイテンシを非表示にします)建築登録を繰り返す)。
ストア フォワーディングを使用したストア バッファは、基本的に「メモリの名前変更」を行います。メモリ ロケーションへのストア/リロードは、このコア内からそのロケーションへの以前のストアおよびロードとは無関係です。(投機的に実行された CPU ブランチに、RAM にアクセスするオペコードを含めることはできますか? )
stack-args 呼び出し規則を使用した関数呼び出しの繰り返し、および/または参照によって値を返すことは、スタック メモリの同じバイトを複数回再利用できる場合です。
最初のストアがまだ入力を待っている場合でも、2 番目のストア/リロードを実行できます。(私はこれをSkylakeでテストしましたが、結果をどこかに回答に投稿したことがある場合はIDK.)