C ++を使用したゲーム作成の状態を研究しているときに、呼び出し規約に出くわしました。
前の質問で、MSDNは_stdcallをうまく説明していないと誰かが言った-私は同意する。
_stdcallのような規約を呼び出す主な目的は何ですか?引数がスタックに配置される順序は重要ですか?X86のコードのサイズをどのように縮小しますか(他の誰かが述べたように)?
C ++を使用したゲーム作成の状態を研究しているときに、呼び出し規約に出くわしました。
前の質問で、MSDNは_stdcallをうまく説明していないと誰かが言った-私は同意する。
_stdcallのような規約を呼び出す主な目的は何ですか?引数がスタックに配置される順序は重要ですか?X86のコードのサイズをどのように縮小しますか(他の誰かが述べたように)?
呼び出し規約がある理由は非常に単純です。そのため、呼び出し元と呼び出し先は、物事がどのように機能するかについて合意します。これがないと、呼び出し元は特定の関数を呼び出すときに引数をどこに置くかわかりません。
マイクロソフトがの具体的な詳細を決定した理由については_stdcall
、それは主に歴史的なものです。MS-DOSでは、すべての呼び出しはレジスタベースであったため、すべてのOS呼び出しにはアセンブリ言語、またはほとんどの高級言語への奇妙な拡張が必要でした。
彼らが最初にWindowsを実行したとき、彼らはcdecl
呼び出し規約を使用しました。これは主に、コンパイラがデフォルトで実行したことであるためです。少なくとも噂によると、Windows 1.0をリリースする準備が整う直前に、Windowsを1枚少ないフロッピーディスクに収めることができるほど効率的だったため、Pascalの呼び出し規約に切り替えました。正確な詳細に関係なく、Pascal呼び出し規約では、呼び出された関数が、関数が呼び出されたすべての場所で引数をクリーンアップする必要がなく、スタックから引数をクリーンアップしたため、コードが少し小さくなりました。少なくとも2つの異なる場所から呼び出された関数の場合、それは勝利です(そして、それが他の場所で同点の場合)。
それから彼らはOS/2での作業を開始し、さらに別の呼び出し規約(syscall)を発明しました。
その後、もちろん、Win32が登場しました。技術的な観点からは、syscallにはそれほど問題はありませんでしたが、(おそらく)OS / 2に関連するすべてのものが汚染されていると見なされたため、syscallを実行する必要がありました。結果は、新しい名前を正当化するのにちょうど十分に異なるものでした。公平に言えば、それは少し誇張です。彼らは本当に便利な追加を1つ追加しました。引数のバイト数を各関数名にエンコードしたので、(たとえば)関数に間違ったプロトタイプを指定した場合、コードは発信者と着信者の間に不一致が生じて、はるかに深刻な問題が発生する可能性があるのではなく、リンクしないでください。
ただし、ほとんどの場合、実際には元のポイントに戻ります。呼び出し規約の正確な詳細は、完全に混乱させない限り、それほど重要ではありません。重要なのは、呼び出し元と呼び出し先が同じことに同意することです。したがって、コンパイラーは、関数が受け入れるパラメーターを知っている場合、それらのパラメーターを関数に正しく取得するためのコードを生成する方法を知っています(同様に、両方が同意します)。スタックのクリーンアップの処理方法など)