タグ付けされた質問 「calling-convention」

8
__stdcallとは何ですか?
私はWin32プログラミングについて学び、WinMainプロトタイプは次のようになります。 int WINAPI WinMain ( HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show ) 私はこのWINAPI識別子が何のためにあるのか混乱し、見つかりました: #define WINAPI __stdcall これは何をしますか?私はこれが戻り値の型の後に何かを持っていることに混乱しています。何の__stdcallため?戻り値の型と関数名の間に何かがある場合、それはどういう意味ですか?

4
Windows64がx86-64上の他のすべてのOSとは異なる呼び出し規約を使用するのはなぜですか?
AMDには、x86-64で使用する呼び出し規約を記述したABI仕様があります。独自のx86-64呼び出し規約があるWindowsを除いて、すべてのOSがこれに従います。どうして? 誰かがこの違いの技術的、歴史的、または政治的な理由を知っていますか、それとも純粋にNIH症候群の問題ですか? OSによっては、より高いレベルのものに対するニーズが異なる可能性があることは理解していますが、たとえば、Windowsでのレジスタパラメータの受け渡し順序rcx - rdx - r8 - r9 - rest on stackが他の誰もが使用してrdi - rsi - rdx - rcx - r8 - r9 - rest on stackいる理由を説明していません。 PS私はこれらの呼び出し規約が一般的にどのように異なるかを知っており、必要に応じて詳細の場所を知っています。私が知りたいのはその理由です。 編集:方法については、たとえばwikipediaのエントリとそこからのリンクを参照してください。

7
コールスタックはどの程度正確に機能しますか?
私はプログラミング言語の低レベルの操作がどのように機能するか、特にそれらがOS / CPUとどのように相互作用するかについて、より深く理解しようとしています。スタックオーバーフローのすべてのスタック/ヒープ関連スレッドのすべての回答を読んだことがあり、それらはすべて素晴らしいものです。しかし、まだ完全には理解していなかったことがあります。 有効なRustコードになる傾向がある疑似コードでこの関数を検討してください;-) fn foo() { let a = 1; let b = 2; let c = 3; let d = 4; // line X doSomething(a, b); doAnotherThing(c, d); } これは、スタックが行Xで次のように見えると想定する方法です。 Stack a +-------------+ | 1 | b +-------------+ | 2 | c +-------------+ | 3 | d +-------------+ …

4
T *をレジスタに渡すことができるのに、unique_ptr <T>はできないのはなぜですか?
私はCppCon 2019でチャンドラー・カルースの講演を見ています: ゼロコストの抽象化はありません その中で、彼は、std::unique_ptr&lt;int&gt;over を使用することによって生じるオーバーヘッドの大きさに驚いた様子の例を示していint*ます。そのセグメントは、およそ17:25の時点で始まります。 彼のサンプルのスニペットのペア(godbolt.org)のコンパイル結果を確認できます。実際、コンパイラーがunique_ptr値を渡そうとはしていないようです。ただのアドレス-レジスタ内、ストレートメモリ内のみ。 Carruth氏が27:00頃に指摘する点の1つは、C ++ ABIが値渡しパラメーター(すべてではないが、一部ではない可能性があります。レジスター内ではなく。 私の質問: これは実際には一部のプラットフォームでのABI要件ですか?(どれですか?)または、特定のシナリオでの悲観化に過ぎないのでしょうか? なぜABIはそのようなのですか?つまり、構造体/クラスのフィールドがレジスター内、または単一のレジスター内に収まる場合、なぜそのレジスター内で渡すことができないのでしょうか? C ++標準委員会は、この点について近年、またはこれまでに議論しましたか? PS-この質問をコードなしで残さないように: 単純なポインタ: void bar(int* ptr) noexcept; void baz(int* ptr) noexcept; void foo(int* ptr) noexcept { if (*ptr &gt; 42) { bar(ptr); *ptr = 42; } baz(ptr); } 一意のポインタ: using std::unique_ptr; void bar(int* ptr) noexcept; void baz(unique_ptr&lt;int&gt; …

3
Windowsでは__cdeclまたは__stdcall?
私は現在、DLLとして配布されるWindows用のC ++ライブラリを開発しています。私の目標は、バイナリの相互運用性を最大化することです。より正確には、DLLの関数は、DLLを再コンパイルしなくても、MSVC ++とMinGWの複数のバージョンでコンパイルされたコードから使用できる必要があります。ただし、どの呼び出し規約が最適cdeclか、またはについて混乱していstdcallます。 「コンパイラ間で同じであることが保証されているのはC呼び出し規約だけです」などのステートメントを聞くことがありますcdecl。これは、「の解釈には、特に値を返す方法にいくつかのバリエーションがあります」などのステートメントとは対照的です。これは、特定のライブラリ開発者(libsndfileなど)が配布するDLLでC呼び出し規約を使用することを、目に見える問題なしに阻止するようには見えません。 一方、stdcall呼び出し規約は明確に定義されているようです。私が聞いたところによると、これはWin32とCOMで使用される規則であるため、すべてのWindowsコンパイラは基本的にそれに従う必要があります。これは、Win32 / COMをサポートしていないWindowsコンパイラはあまり役に立たないという仮定に基づいています。フォーラムに投稿された多くのコードスニペットは関数を宣言していますがstdcall、理由を明確に説明する単一の投稿を見つけることができないようです。 矛盾する情報が多すぎて、実行する検索ごとに異なる回答が得られるため、2つを判断するのに役立ちません。なぜどちらかを選択する必要があるのか​​(または2つが同等である理由)について、明確で詳細な議論のある説明を探しています。 ほとんどのクライアントコードは、「インターフェース」、純粋仮想クラス(次のパターンは、例えば説明を通じて、私のDLLとのインタフェースになるので、この質問は、「古典的な」機能に、だけでなく、仮想メンバ関数の呼び出しに適用されるだけでなく、注意こことそこ)。

1
スタックメモリが使用されていないときに割り当てられるのはなぜですか?
次の例を考えてみます。 struct vector { int size() const; bool empty() const; }; bool vector::empty() const { return size() == 0; } 生成されたアセンブリコードvector::empty(clangによる最適化あり): push rax call vector::size() const test eax, eax sete al pop rcx ret なぜスタックスペースを割り当てるのですか?一切使用しておりません。省略することができます。MSVCとgccの最適化ビルドもこの関数にスタックスペースを使用するため(godboltを参照)、理由があるはずです。pushpop
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.