
からint80h.org、FreeBSD アセンブリ言語チュートリアル
[Linux 呼び出し] 規則は、少なくともアセンブリ言語プログラミングに関する限り、Unix の方法に比べて大きな欠点があります。カーネル呼び出しを行うたびに、レジスタをプッシュし、後でポップする必要があります。これにより、コードが大きくなり、遅くなります。
FreeBSDはLinuxコンベンションと「Unixコンベンション」の両方をサポートしていると書かれています。
FreeBSD 専用にコーディングする場合は、常に Unix 規則を使用する必要があります。Unix 規則の方が高速で、グローバル変数をレジスタに格納でき、実行可能ファイルにブランドを付ける必要がなく、ターゲット システムに Linux エミュレーション パッケージのインストールを強制する必要もありません。
Linux の方が重くて遅いというのは奇妙に思えます。2 つの選択肢があるようです。
- 保存する必要があるレジスタのみを保存します。
- システムコールによって破壊される可能性のある揮発性レジスタ(私の知る限り
ecx
) - または、適切な引数をカーネルに送信して、(、、、、、
syscall
などeax
)を作成するために必要なレジスタ。ecx
edx
esi
edi
ebp
- システムコールによって破壊される可能性のある揮発性レジスタ(私の知る限り
- カーネルへの引数の 100% をスタックに保存します。
FreeBSDのほうが最悪Linux コンベンションのケース シナリオ。何が足りないのでしょうか? FreeBSD コンベンション (「Unix 方式」と呼ばれる) は、なぜより軽量で高速なのでしょうか?
答え1
私の意見では、これは結局のところ著者の意見に帰着します。
FreeBSD (“Unix”) の規則では、引数をスタックにプッシュし、 でシステム コール番号を指定してEAX
、割り込み 0x80 を呼び出します (別の関数から呼び出されることが予想されるため、スタック上に追加のオペランドがあります)。
Linux i386 規則では、引数を適切なレジスタに配置し、割り込み 0x80 を呼び出します。
かさばる/遅いという議論は、Linuxの慣例により、発信者レジスタの使用に対処する必要があります。システム コールが、呼び出し元が関心を持つ値を含むレジスタ内の引数を必要とする場合、それらを保持する必要があり、その結果、追加の作業が発生します。Cライブラリのこの例を参照してくださいこの例では、システムコールはEAX、EBX、EDX、EDI、ESIの値を必要としますが、呼び出し側はEBX、EDI、ESIの保持のみを気にするため、これらだけをスタックにプッシュします。一般的なケースは次のようになります。かなり複雑(ただし、これは C とアセンブリ言語の混合を扱い、すべてのケースで最適なコードを生成しようとした結果でもあります)。ただし、あなたが参照しているサイトのポイントであるアセンブリ言語で記述する場合、それはそれほど問題にはなりません。
私には6つ半のように思えます。FreeBSDの慣例では常にスタックにプッシュしますが、Linuxの慣例ではすべての場合にスタックにプッシュします(または他の場所にプッシュします)。Linuxの慣例ではすべてレジスタで計算できるため、コードの高速化が可能になると主張することもできます...ロブしかし、Linux ではレジスタがプッシュされてしまう (struct pt_regs
システム コールを処理する C 関数に引数を提供するのに使用されるインスタンスを構築するため) ため、全体的なコストは FreeBSD 側よりも Linux 側の方が大きくなると指摘しています。
いずれにしても、システム コール自体の実行コストを考えると、システム コール周辺のスタックまたはレジスタ ベースのコードについて話すときにパフォーマンスについて議論するのは、かなり杓子定規なように思えます。節約されるサイクルは絶対的には良いことなのですが、相対的な改善はごくわずかです。