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 の回答を参照してください。)