23

私は暗号化プログラムを作成していますが、コア (ワイド乗算ルーチン) は x86-64 アセンブリで作成されています。これは、速度と、adcC から簡単にアクセスできないような命令を頻繁に使用するためです。インライン化したくありません。この関数は大きく、内側のループで数回呼び出されるためです。

理想的には、この関数のカスタム呼び出し規則も定義したいと思います。これは、内部ですべてのレジスタ ( を除くrsp) を使用し、引数を上書きせず、レジスタに返すためです。現時点では、C 呼び出し規則に適合していますが、もちろんこれにより速度が低下します (約 10%)。

これを避けるために、私はそれを呼び出すことができますasm("call %Pn" : ... : my_function... : "cc", all the registers);が、呼び出し命令がスタックを混乱させることをGCCに伝える方法はありますか? そうしないと、GCC はこれらすべてのレジスタをレッド ゾーンに配置し、一番上のレジスタが上書きされます。モジュール全体を -mno-red-zone でコンパイルできますが、GCC に、たとえば、レッド ゾーンの上位 8 バイトが上書きされて何も配置されないようにする方法を希望します。

4

5 に答える 5

5

あなたの最初の質問から、私はgccがリーフ機能へのレッドゾーンの使用を制限していることに気づいていませんでした。これはx86_64ABIで必要とは思われませんが、コンパイラーにとっては合理的な単純化の前提です。その場合、コンパイルの目的で、アセンブリルーチンを呼び出す関数を非リーフにするだけで済みます。

int global;

was_leaf()
{
    if (global) other();
}

GCCはglobal、真になるかどうかを判断できないため、呼び出しを最適化できないためother()was_leaf()リーフ関数ではなくなります。私はこれをコンパイルし(スタックの使用をトリガーするより多くのコードを使用して)、リーフとして移動せず%rsp、変更を加えると移動することを確認しました。

また、リーフに128バイト(ちょうど)以上を単純に割り当てようとchar buf[150]しましたが、部分的な減算しか行われていないことにショックを受けました。

    pushq   %rbp
    movq    %rsp, %rbp
    subq    $40, %rsp
    movb    $7, -155(%rbp)

葉を壊すコードを元に戻すと、subq $160, %rsp

于 2011-06-18T19:32:10.077 に答える
2

関数へのエントリ時にスタックポインタを128バイトシフトすることにより、x86-64 ABIの信号の要件を満たすようにアセンブリ関数を変更することはできませんか?

または、リターンポインター自体を参照している場合は、シフトを呼び出しマクロに入れます(so sub %rsp; call...

于 2011-06-17T22:38:16.810 に答える
0

よくわかりませんが、関数属性のGCCドキュメントを見るstdcallと、興味深い関数属性が見つかりました。

asm呼び出しバージョンで何が問題になるのかまだ疑問です。美学だけの場合は、マクロまたはインライン関数に変換できます。

于 2011-06-17T22:31:39.697 に答える