Intel アーキテクチャ IA32 では、movl や movw などの命令は、両方がメモリ ロケーションであるオペランドを許可しません。たとえば、命令 movl (%eax), (%edx) は許可されていません。なんで?
4 に答える
その答えには、RAM を十分に理解することが必要です。簡単に言うと、RAM は読み取りモードまたは書き込みモードの 2 つの状態しかありません。RAM 内の 1 バイトを別の場所にコピーする場合は、読み取りから書き込みに切り替えるときに、RAM の外部に一時的なストレージ領域が必要です。
アーキテクチャがそのような RAM から RAM への命令を持つことは確かに可能ですが、マイクロコードではデータを RAM からレジスタにコピーしてから RAM に戻すように変換する高レベルの命令になります。あるいは、RAM コントローラーを拡張して、このデータのコピー専用の一時レジスターを持たせることもできますが、 CPU とハードウェアのやり取りが複雑になるため、あまりメリットはありません。
編集:ハイブリッド メモリ キューブや高帯域幅メモリなどの最近の進歩は、RAM トポロジがより PCI-e に似たアーキテクチャであり、RAM から RAM への直接転送が可能になったことは注目に値しますが、それはサポート ロジックによるものです。 RAM自体ではなく、テクノロジーのためです。CPU アーキテクチャでは、これは単一の命令の形式ではなく、DMA のように一度に RAM の巨大なブロックの形式になります。さらに、CPU キャッシュは従来の RAM のように動作するため、アーキテクチャはそれを次のように抽象化する必要があります。私の元の説明によると
EDIT2:@PeterCordes のコメントによると、私の最初の理解は完全には正しくありませんでした。実際、x86 にはいくつかのメモリからメモリへの命令があります。ほとんどの命令 (movl や movw など) で使用できない本当の理由は、命令のエンコードの複雑さを低く抑えるためですが、それらを実装することはできたはずです。ただし、RAMの外部にラッチまたはレジスタの形式で一時的な保存場所があるという私の最初の回答の基本的な考え方は正しいですが、これがこれらの命令が存在しない理由であるという考えはそうではありません。6502 や 8086 などの 1970 年代の古いチップでさえ、メモリからメモリへの命令があり、INC などの操作を RAM の場所で直接簡単に実行できます。
ia32 は x86 で、x86 は Intel 8086 (iAPX 86) からの進化です。これは、8 ビットの命令セットに基づく小型で安価なチップであり、2 つの明示的なメモリ オペランドを持つ "mov" はありませんでした。
ウィキペディアの著者は、8086 の命令エンコーディングについて次のように説明しています。
8 ビット プロセッサに着想を得たコンパクトなエンコードにより、ほとんどの命令は 1 アドレスまたは 2 アドレスの演算であり、結果はオペランドの 1 つに格納されます。オペランドの最大 1 つをメモリ内に置くことができますが、このメモリ オペランドはデスティネーションにすることもできますが、もう 1 つのオペランド (ソース) はレジスタまたはイミディエートにすることができます。1 つのメモリ ロケーションをソースとデスティネーションの両方として使用できることも多く、これは当時のほとんどの 8 ビット マシンに匹敵する (多くの場合それよりも優れた) コード密度に貢献しました。
一部の CISC には、メモリ間命令 (2 つのメモリ オペランドを操作する単一の命令) が含まれていました。講義https://www.cis.upenn.edu/~milom/cis501-Fall05/lectures/02_isa.pdfでは、VAX がメモリ間命令をエンコードできると述べています。
DEC VAX (PDP-11 への仮想アドレス拡張): 1977
- • 可変長命令: 1 ~ 321 バイト!!!
- • 14 個の GPR + PC + スタック ポインタ + 条件コード
- • データ サイズ: 8、16、32、64、128 ビット、10 進数、文字列
- •すべてのデータ サイズに対応するメモリ - メモリ命令
- • 特別な insns: crc、insque、polyf、および数百のキャスト
これは VAX 用の OpenBSD memcpy ソースです (命令セットマニュアルhttp://h20565.www2.hpe.com/hpsc/doc/public/display?docId=emr_na-c04623178 ):
movq 8(ap),r1 /* r1 = src, r2 = length */
movl 4(ap),r3 /* r3 = dst */
...
1: /* move forward */
cmpl r2,r0
bgtru 3f /* stupid movc3 limitation */
movc3 r2,(r1),(r3) /* move it all */
ここでの「movc3」命令には 2 つのメモリ オペランドがあり、これらのアドレスはレジスタに格納されます。
x86には、メモリ間操作を行う「文字列」命令がいくつかあります(*s、特にmovs - http://x86.renejeschke.de/html/file_module_x86_id_203.html)が、この命令は事前定義されたレジスタSIおよびDIをアドレスとして使用します(暗黙のオペランド)、および 2 つのメモリ オペランドは x86 でエンコードできません。
私の知る限り、このアーキテクチャの原則として、命令ごとに1つのメモリアクセスのみが許可されます。これは、命令ごとに2つのメモリアクセスを処理すると、プロセッサの実行パイプラインが複雑になるためです。
RAM は入力と出力をサポートしますが、コピーはサポートしません。したがって、メモリからメモリへの移動は、実際にはメモリから CPU からメモリへの移動になります。理論的にはそのような命令を実装することは可能ですが、あまり実用的ではないため、おそらくそうではありませんでした.
このような命令を実装するために考慮する必要があることのいくつかを次に示します。
どの一時保管場所を使用しますか? レジスター?
レジスターを使用する場合、どれをハイジャックしますか?
そのような命令を提供しないと、上記の問題はプログラマーに委ねられます。