[解決済み] i386およびx86-64におけるUNIXおよびLinuxシステムコール(およびユーザースペースファンクション)の呼び出し規約は?
質問内容
以下のリンクは、UNIX (BSD flavor) & Linux の x86-32 システムコール規約を説明するものです。
しかし、UNIX & Linuxの両方におけるx86-64システムコールの規約はどうなっているのでしょうか?
解決方法は?
各トピックの詳細については、こちらをご覧ください。 Linuxシステムコールの決定版
LinuxのGNU Assembler(gas)で検証してみました。
カーネルインターフェース
x86-32 aka i386 Linux System Call convention:
x86-32では、Linuxシステムコールのパラメータはレジスタを使用して渡されます。
%eax
には、syscall_number を指定します。 ebx, %ecx, %edx, %esi, %edi, %ebp はシステムコールに6つのパラメータを渡すために使用されます。
戻り値は
%eax
. 他のすべてのレジスタ(EFLAGS を含む)は
int $0x80
.
次のスニペットを Linux アセンブリチュートリアル しかし、これには疑問があります。どなたか例を示していただけると幸いです。
<ブロッククオート
引数が6個以上ある場合。
%ebx
を含む必要があります。
引数のリストがある場所
が格納されていますが、これは気にしないでください。
を使うことはまずないでしょうから。
6つ以上のシステムコールを持つ
の引数を指定します。
例ともう少し読むには、以下を参照してください。
http://www.int80h.org/bsdasm/#alternate-calling-convention
. を使った i386 Linux 用の Hello World の別の例です。
int 0x80
:
Linuxのシステムコールを使ったアセンブリ言語によるHello, world?
32ビットシステムコールを行うには、より高速な方法があります。
sysenter
. カーネルは、すべてのプロセス(vDSO)にメモリのページをマッピングし、ユーザースペース側の
sysenter
ダンスは、カーネルがリターン・アドレスを見つけることができるように協力する必要があります。 Argからレジスタへのマッピングは
int $0x80
. を使用する代わりに、通常は vDSO にコールする必要があります。
sysenter
を直接使用します。 (参照
Linuxシステムコールの決定版
については、vDSOへのリンクと呼び出しに関する情報、および
sysenter
その他、システムコールに関することなら何でも。)
x86-32 [Free|Open|Net|DragonFly]BSD UNIX System Call convention:
パラメータはスタック上に渡されます。パラメータをスタックにプッシュする(最後のパラメータが最初にプッシュされる)。その後、32ビットのダミーデータ(実際にはダミーデータではありません)を追加して、システムコール命令を実行します。
int $0x80
http://www.int80h.org/bsdasm/#default-calling-convention
x86-64 Linux システムコール規約。
(注 x86-64 Mac OS Xは似ているが異なる Linuxから。 TODO: *BSD がどうなっているかをチェックしてください)
参照:「A.2 AMD64 リナックス の「カーネル規約」(Kernel Conventions") を参照してください。 System V Application Binary Interface AMD64 Architecture Processor Supplement (英語) . i386 および x86-64 System V psABI の最新バージョンは、以下の URL でご覧になれます。 このページからリンクされている ABI メンテナレポジトリの . (また x86 タグの wiki には最新の ABI リンクやその他 x86 asm に関する良い情報がたくさんあります)。
このセクションのスニペットを紹介します。
- ユーザレベルのアプリケーションは、整数レジスタとして、以下のものを渡すために使用します。 シーケンス %rdi、%rsi、%rdx、%rcx。 r8と%r9があります。 カーネル・インターフェースは、%rdi, %rsi, %rdx, %r10, %r8, %r9 を使用します。
- システムコールは
syscall
命令 . この は、%rcx と %r11 を抑制します。 と%raxの戻り値だけでなく、他のレジスタは保存されます。- システムコールの番号は、レジスタ %rax に渡さなければなりません。
- システムコールの引数は6個までで、引数が渡されることはありません。 を直接スタックに載せる。
- システムコールから戻ると、レジスタ %rax にその結果が格納されます。 システムコールの 4095から-1の範囲の値は エラーであれば
-errno
.- クラスINTEGERまたはクラスMEMORYの値のみがカーネルに渡されます。
これはABIのLinux固有の付録であり、Linuxであっても規範的なものではなく、参考となるものであることを忘れないでください。 (しかし、実際には正確です)。
この32ビット
int $0x80
ABI
は
64ビットコードで使用可能です(ただし、強くは推奨しません)。
64ビットコードで32ビットint 0x80 Linux ABIを使用した場合どうなりますか?
入力は32ビットに切り捨てられるので、ポインタには適さず、r8-r11がゼロになります。
ユーザーインターフェース:関数の呼び出し
x86-32 関数呼び出しの規約。
x86-32では、パラメータはスタック上で渡されました。最後のパラメータは、すべてのパラメータが終了するまで、最初にスタックにプッシュされ、その後
call
という命令が実行されました。これは、LinuxでCライブラリ(libc)の関数をアセンブリから呼び出すときに使用されます。
Linux で使用されている i386 System V ABI の最新バージョンでは、16 バイトのアライメントが必要です。
%esp
の前に
call
x86-64 System V ABI が常に要求しているようなものです。 Callees はそれを前提として、SSE の 16 バイトのロード/ストアを使用し、アラインメント無しでフォールトすることが許されています。 しかし、歴史的に見ると、Linux は 4 バイトのスタックアライメントしか必要としないので、8 バイトの
double
などがあります。
他の最新の32ビットシステムの中には、いまだに4バイト以上のスタックアライメントを必要としないものもあります。
x86-64 System V ユーザースペースの関数呼び出しの規則。
x86-64 System V は、i386 System V のスタック引数規約よりも効率的な、レジスターでの引数渡しを採用しています。 これは i386 System V のスタック引数規約よりも効率的で、引数をメモリ (キャッシュ) に格納してから呼び出し側で再びロードするというレイテンシと余分な命令を回避することができます。 これは利用可能なレジスタが多いためうまく機能し、レイテンシとアウトオブオーダー実行が重要な最近の高性能CPUに適しています。 (i386 ABIは非常に古い)。
この中で 新しい という機構があります。まず、パラメータはクラスに分けられます。各パラメータのクラスによって、呼び出される関数に渡される方法が決まります。
の「3.2 関数呼び出しのシーケンス」を参照してください。 System V Application Binary Interface AMD64 Architecture Processor Supplement (英語) という文章があり、その一部をご紹介します。
引数が分類されると、レジスタが割り当てられます(順番に)。 左から右の順番で)次のように渡します。
- クラスがMEMORYの場合、スタック上の引数を渡します。
- クラスが INTEGER の場合、次に利用可能なレジスタを選択します。 rdi, %rsi, %rdx, %rcx, %r8 および %r9 のシーケンスが使用されます。
そこで
%rdi, %rsi, %rdx, %rcx, %r8 and %r9
はレジスタ
順番に
アセンブリから libc の関数に整数/ポインタ (すなわち INTEGER クラス) のパラメータを渡すために使用します。最初の INTEGER パラメータには %rdi が使われます。 2番目は%rsi、3番目は%rdxといった具合です。次に
call
命令を与える必要があります。 スタック(
%rsp
の場合、16Bアラインでなければなりません。
call
が実行されます。
INTEGERパラメータが6個以上ある場合、7個目以降のINTEGERパラメータはスタックに渡される。 (呼び出し側がポップします。x86-32と同じです。)
最初の 8 個の浮動小数点引数は %xmm0-7 で渡され、後でスタックに積まれます。 コールプリザーブドベクトルレジスタはありません。 (FP と整数の引数を混在させた関数は、合計 8 個以上のレジスタ引数を持つことができます)。
可変個体関数(
のように
printf
が常に必要です。
%al
= FPレジスタの引数の数。
構造体をいつレジスタに詰めるかについては、ルールがあります (
rdx:rax
を使用する場合と、メモリ上に置く場合があります。 詳細はABIを参照してください。また、コンパイラの出力をチェックして、コードがどのように受け渡しされるべきかについてコンパイラと一致することを確認してください。
注意事項 Windows x64の関数呼び出し規則 は、x86-64 System V とは複数の重要な違いがあります。 が必要です。 また、xmm6-xmm15 は呼び出し側で予約されています。 また、どの arg をどのレジスタに入れるかについてのルールも大きく異なっています。
関連
-
Linuxのデスクトップの背景を画像で引き伸ばし表示にする方法とは?
-
中国版「浮世」を含むUbuntu 20.04.2リリース
-
LinuxでJenkinsプラグインのインストールが遅い場合の解決策
-
[解決済み] bash sh - command not found [重複].
-
[解決済み] Bashでファイルの中身をループする
-
[解決済み] php.iniはどこにありますか?
-
[解決済み] 1サイクルあたり4FLOPの理論上の最大値を達成するにはどうすればよいですか?
-
[解決済み] アプリケーション・バイナリ・インターフェース(ABI)とは何ですか?
-
[解決済み] WindowsとLinuxのディレクトリ名で禁止されている文字は何ですか?
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
centos7 インストール クリックハウスとセット ユーザー名 パスワード ケース 詳細
-
ロックされたdeepinファイルを削除する方法は?deepinのロック付きファイルを削除する方法のヒント
-
deepin linuxからmacosx仮想マシンに直接ファイルをドラッグ&ドロップする方法は?
-
deepin linuxでroot権限に切り替えるには?Deepinでrootに切り替えるためのヒント
-
Linux 5.10.10 正式版リリース:NULLポインタの不具合修正など。
-
deepin20のソフトをアンインストールする方法を教えてください。deepinのアプリケーションをアンインストールする2つの方法
-
TclError: 表示名がなく、$DISPLAY環境変数もない。
-
TclError: 表示名がなく、$DISPLAY環境変数もない。
-
エラーの解決方法 お客様のバージョンは /bin/bash: java: コマンドが見つかりませんでした。
-
apache startup error (98) Address already in use: make_sock: could not bind to...