アキュムレータベースのCPUアーキテクチャとレジスタベースのCPUアーキテクチャの違いがわかりません。 x86はレジスタベースですが、アキュムレータのようなレジスタがあります。スタックベースとレジスタベースの違いを尋ねる人だけが聞こえますが、レジスタベースとアキュムレータベースは違います。それぞれの長所と短所は何ですか?また、それぞれからアセンブリコードの例をいくつか入手できますか?
レジスタベースのCPUアーキテクチャには、1つまたは複数の汎用レジスタがあります(「汎用レジスタ」には、スタックポインタや命令ポインタなどの特殊目的レジスタは含まれません)。
アキュムレータベースのCPUアーキテクチャは、1つの汎用レジスタ(アキュムレータ)のみを持つレジスタベースのCPUアーキテクチャです。
「1つ以上の汎用レジスター」の主な利点は、コンパイラーがスタックに一時的な値ほど「スピル」する必要がないことです。また、CPUがより多くの独立した命令を並行して実行する方が簡単です。
例として、a = (b - c) + (d - f) + 123
を実行するとします。 「りんご対りんごの比較」では、両方の例でIntel構文32ビット80x86アセンブリを使用します(ただし、アキュムレータベースのCPUアーキテクチャにはEAXのみを使用します)。
アキュムレータベースのCPUアーキテクチャの場合、次のようになります。
_ mov eax,[b] ;Group 1
sub eax,[c] ;Group 2
add eax,123 ;Group 3
mov [a],eax ;Group 4
mov eax,[d]
sub eax,[e] ;Group 5
add [a],eax ;Group 6
_
これらの命令のほとんどは、前の命令の結果に依存するため、並行して実行できないことに注意してください。 「;グループN」コメントは、どのグループの命令を並行して実行できるかを示すためにあります(また、内部の「レジスタの名前変更」機能の何らかの形を想定すると、「グループ4」が、2つの命令が実行する可能性が高い唯一のグループであることを示します並行して行われます)。
複数のレジスターを使用すると、次の結果が得られます。
_ mov eax,[b] ;Group 1
mov ebx,[d]
sub eax,[c] ;Group 2
sub ebx,[e]
lea eax,[eax+ebx+123] ;Group 3
mov [a],eax ;Group 4
_
この場合、命令が1つ少なく、命令のグループが2つ少なくなります(より多くの命令が並行して実行される可能性が高くなります)。それは実際には「25%速い」ことを意味するかもしれません。
もちろん実際には、コードは比較的単純な計算以上のものを実行します。したがって、「より多くの命令を並行して」実行する可能性がさらに高くなります。例えば;レジスタが2つだけ(ECXとEDXなど)あれば、a = (b - c) + (d - f) + 123
とg = (h - i) + (j - k) + 456
を同じ時間で実行できることを簡単に確認できます(両方の計算を異なるレジスタ);また、アキュムレータベースのCPUアーキテクチャでは、計算を並列に実行できないことも簡単にわかるはずです(2つの計算は、1つの計算の2倍の時間がかかります)。
注:ここで私が書いたものには、少なくとも1つの「潜在的な技術的不正確さ」があります(主にレジスタの名前変更の理論的な機能と、アキュムレータベースのCPUアーキテクチャでのアプリケーションに関係しています)。これは意図的なものです。詳細に詳しくしすぎると(「100%技術的に正確」になり、すべての小さなケースをカバーするため)、関連する部分を理解するのが非常に難しくなります。
違いは、私の考えでは、オペランドの指定方法にあります。
スペクトラムの一端では、レジスタアーキテクチャは、addなどの2項演算の3つのオペランドすべての指定をサポートできます。明示的なオペランドを1つだけサポートできます。 (スタック設計はさらに極端で、オペランドの場合は何も指定しません!)
多くのアーキテクチャでは、1つ、2つ、または3つのオペランドの2項演算命令(加算など)をISAにブレンドするため、アーキテクチャ全体を特徴付けるのが難しくなるため、個々の命令を詳しく調べる必要があります。
基本的なトレードオフは、命令のサイズと中間の計算を再利用する能力です。指定されたオペランドの数が少ないスタイルでは、命令のエンコーディングは短くなりますが、結果はソースオペランドを上書きし、他のオプションも制限します。
一部のコードシーケンスでは、2つのオペランド命令が1つの3オペランド命令と同じ結果を達成するために2つの命令を使用する必要がある場合があります。他のコードシーケンスでは、どちらも同じ数の命令を使用します。つまり、オペランドのバージョンが少ないほど、命令が短くなる可能性があります。
たとえば、レジスタAとBに値があるとします。2オペランド形式を使用してそれらを追加するには、AをBに追加してBを破棄するか、BをAに追加して(Aを破棄)します。この上書き/破棄がわかりました。しかし、そうでなければ、1つのオペランド(たとえばA)をレジスタCにコピーしてから、BをCに追加する必要があります-2つの命令!
3つのレジスター命令は、どちらの入力ソースも破壊することなく、AからBをCに追加できました。