GNU/Linux >> Linux の 問題 >  >> Linux

x86_64 アセンブリ Linux システム コールの混乱

i386 と x86_64 の間では、カーネルに入るために使用される命令と、システム コール引数を運ぶために使用されるレジスタの両方を含め、かなり多くの変更がありました。これはあなたのものと同等のコードです:

.section .data

.section .text
.global _start
_start:
movq $60, %rax
movq $2, %rdi
syscall

この回答から関連する質問への引用:

<ブロック引用>

syscall 番号は、arch/x86/include/asm/unistd_64.h の下の Linux ソース コードにあります。 syscall 番号は rax レジスタに渡されます。パラメータは、rdi、rsi、rdx、r10、r8、r9 にあります。呼び出しは、「syscall」命令で呼び出されます。 syscall は rcx レジスタを上書きします。戻り値は rax です。


i386 と x86_64 の間に驚くべき違いが 1 つあります。それらは同じシステム コール メカニズムを使用していません。正しいコードは次のとおりです:

movq $60, %rax
movq $2,  %rdi   ; not %rbx!
syscall

割り込み 0x80 常に 32 ビット システム コールを呼び出します。 32 ビット アプリケーションを 64 ビット システムで実行できるようにするために使用されます。

学習のために、その場で 64 ビットに変換するのではなく、チュートリアルに正確に従うようにしてください。他にもいくつかの重要な動作上の違いがあり、遭遇する可能性があります。 i386 に慣れたら、 x86_64 を個別に入手できます。


これを読んでくださいx86-64でのUNIXおよびLinuxシステムコールの呼び出し規約は何ですか

int 0x80 を使用していることに注意してください x64 システムの syscall は古い互換性レイヤーです。 syscall を使用する必要があります x64 システムでの説明

この古い方法を引き続き使用できますが、バイナリを x86 モードでコンパイルする必要があります。詳細については、コンパイラ/アセンブラのマニュアルを参照してください。


Duskwuff の回答は、システム コールのメカニズムが 64 ビット x86 Linux と 32 ビット Linux で異なることを正しく指摘しています。

ただし、この回答は不完全であり、いくつかの理由で誤解を招きます:

  • この変更は、64 ビット システムが普及する前に導入されました。 、 int 0x80 という観察に動機付けられました Pentium 4 では非常に遅かった。Linus Torvalds が SYSENTER を使用して解決策をコーディング /SYSEXIT 命令 (Intel によって Pentium Pro 時代に導入されたものでしたが、バグが多く、実用的な利点はありませんでした)。したがって、最新の 32 ビット Linux システムでは実際に SYSENTER を使用しています 、 int 0x80 ではありません .
  • 64 ビット x86 Linux カーネルは実際には SYSENTER を使用しません そして SYSEXIT .彼らは実際に非常によく似た SYSCALL を使用しています /SYSRET

コメントで指摘されているように、 SYSENTER 多くの 64 ビット Linux システムでは実際には動作しません —つまり、64 ビット AMD システム。

確かに紛らわしい状況です。悲惨な詳細はここにありますが、結論は次のとおりです:

<ブロック引用>

32 ビット カーネルの場合、互換性のあるペアは SYSENTER/SYSEXIT のみです [AMD と Intel CPU 間]

ロング モードの 64 ビット カーネルの場合のみ… SYSCALL/SYSRET が唯一の互換性のあるペアです [AMD と Intel CPU 間]

Intel では 64 ビット モードの CPU、SYSENTER を使用して回避できます SYSCALL と同じことをするからです。 、ただし、これは AMD システムには当てはまりません。

結論:常に SYSCALL を使用してください 64 ビット x86 システム上の Linux .これは、x86-64 ABI が実際に指定しているものです。 (さらに詳細については、このすばらしい wiki の回答を参照してください。)


Linux
  1. Linux –新しいカーネルのシステムコール呼び出しメソッド?

  2. Linuxでclone()システムコールのスタックをmmapする方法は?

  3. アセンブリの Linux システム コール テーブルまたはチートシート

  1. 最速の Linux システム コール

  2. パラメータをLinuxシステムコールに渡す方法は?

  3. Linux でシステム コール テーブルを変更する必要があるのはなぜですか?

  1. C 言語による Linux システム プログラミングのベスト コーディング プラクティス – パート 1

  2. インラインアセンブリでsyscallまたはsysenterを介してシステムコールを呼び出す方法は?

  3. x86 と x86_64 の Linux システムコール番号が異なるのはなぜですか?