5

なぜプッシュやポップのようなコマンドがあるのですか?

私が理解poppushていることから、基本的にはそれぞれ( movthen add)と(subthen mov)を実行するのと同じespです。


たとえば、次のことはしません。

pushl %eax

と同等である:

subl $4, %esp
movl %eax, (%esp-4)

スタックアクセスがない場合は修正してください(%esp-4)、私はまだアセンブリを学習しています


私が見ることができる唯一の真の利点は、両方の操作を同時に行うことがいくつかの利点を提供するかどうかです。しかし、どうすればよいかわかりません。

4

3 に答える 3

8

CALLしかし、それでは、指示の理由もありません。結局のところ、次の方法で通話をシミュレートできます。

sub esp,4
mov [esp-4], offset return_address
jmp myproc

RETまた、次の方法でシミュレートできるため、命令も必要ありません。

mov eax,[esp]
add esp,4
jmp [eax]

よく見ると、他の命令を組み合わせてシミュレートできる命令がたくさんあります。ポイントは何ですか?

この種の質問に対する答えは、x86 プロセッサ ファミリの長い歴史と、それ以前のプロセッサに根ざしています。設計者は、プログラマがプロセッサをどのように使用するかを研究し、実行速度とメモリ使用の点で効率的な命令セットを作成しました。

70 年代後半には、64 キロバイトは大量の RAM であり、RAM ははるかに低速でした。すべての命令バイトは貴重であり、メモリから命令をフェッチするだけで膨大な量のオーバーヘッドがありました。命令フェッチが実行よりも長くかかることは珍しくありませんでした。そのため、可能な限り少ない命令バイトでエンコードすることで、パフォーマンスが大幅に向上しました。

RAM は、CPU のクロック速度と比較すると依然として信じられないほど遅いため、できるだけ少ない命令バイトでエンコードすることで得られる利点があります。分岐予測やプリフェッチ ロジックと同様に、大規模な CPU キャッシュが大いに役立つことは事実ですが、RAM から CPU キャッシュに転送されるすべてのバイトは依然として高価です。命令エンコーディングを倹約することは報われます。

呼び出し手順について:

アセンブリ言語でプロシージャを呼び出す標準的な方法は、パラメータをプッシュしてからプロシージャをプッシュするcallことです。たとえば、これは 2 つの dword 値を渡します。

push eax
push ebx
call proc    ; pushes the return address and jumps to proc
...

proc:
  ; at this point, [esp] contains the return address

命令はret戻りアドレスを命令ポインターにポップします。

もちろん、誰かがスタックをクリーンアップする必要があります。呼び出し元は、スタック ポインターをインクリメントすることで、スタックをクリーンアップできます。または、呼び出されたプロシージャは、を使用してスタックをクリーンアップできます。これによりret 8、リターン アドレスがポップされ、スタック ポインタがインクリメントされます。

呼び出し規則の詳細については、 http://www.delorie.com/djgpp/doc/ug/asm/calling.htmlを参照してください。

于 2012-04-14T20:09:53.197 に答える
2

良い。2 つの命令がある場合は、おそらくより多くのスペースを使用します。より多くのデータを転送するにはCPUが必要です。そしてそれにはもっと時間がかかります。通常、2 つの別々の命令も、より多くの CPU リソースを必要とします。CPUがそれらを並列化したとしても、フェッチャー、デコーダーにはさらに多くの作業があります...絶対に必要な命令以外をすべて削除しようとすると、チューリングマシンになってしまいます。究極のリスクですが、実際にはあまり効果的ではありません。

于 2012-04-14T21:50:28.940 に答える
1

1 オペコード > 2 オペコード、少なくとも CPU 使用率を削減しようとしている場合。

于 2012-04-14T17:26:57.350 に答える