Cukup banyak yang berubah antara i386 dan x86_64 termasuk instruksi yang digunakan untuk masuk ke kernel dan register yang digunakan untuk membawa argumen panggilan sistem. Ini kode yang setara dengan milik Anda:
.section .data
.section .text
.global _start
_start:
movq $60, %rax
movq $2, %rdi
syscall
Mengutip dari jawaban ini untuk pertanyaan terkait:
Nomor syscall ada di kode sumber Linux di bawah arch/x86/include/asm/unistd_64.h. Nomor syscall dilewatkan dalam register rax. Parameternya ada di rdi, rsi, rdx, r10, r8, r9. Panggilan dipanggil dengan instruksi "syscall". Syscall menimpa register rcx. Pengembaliannya dalam rax.
Anda mengalami satu perbedaan mengejutkan antara i386 dan x86_64:keduanya tidak menggunakan mekanisme panggilan sistem yang sama. Kode yang benar adalah:
movq $60, %rax
movq $2, %rdi ; not %rbx!
syscall
Interupsi 0x80
selalu memanggil panggilan sistem 32-bit. Ini digunakan untuk mengizinkan aplikasi 32-bit berjalan di sistem 64-bit.
Untuk tujuan pembelajaran, Anda mungkin harus mencoba mengikuti tutorial dengan tepat, daripada menerjemahkan dengan cepat ke 64-bit -- ada beberapa perbedaan perilaku signifikan lainnya yang mungkin Anda temui. Setelah Anda terbiasa dengan i386, lalu Anda dapat mengambil x86_64 secara terpisah.
silakan baca ini Apa konvensi pemanggilan untuk panggilan sistem UNIX &Linux di x86-64
dan perhatikan bahwa menggunakan int 0x80
untuk syscall pada sistem x64 adalah lapisan kompatibilitas lama. Anda harus menggunakan syscall
instruksi pada sistem x64.
Anda masih dapat menggunakan metode lama ini, tetapi Anda perlu mengkompilasi binari Anda dalam mode x86, lihat manual compiler/assembler Anda untuk detailnya.
jawaban senjawuff menunjukkan dengan benar bahwa mekanisme panggilan sistem berbeda untuk Linux x86 64-bit versus Linux 32-bit.
Namun, jawaban ini tidak lengkap dan menyesatkan karena beberapa alasan:
- Perubahan ini sebenarnya diperkenalkan sebelum sistem 64-bit menjadi populer , termotivasi oleh pengamatan bahwa
int 0x80
sangat lambat di Pentium 4. Linus Torvalds membuat kode solusi menggunakanSYSENTER
/SYSEXIT
instruksi (yang telah diperkenalkan oleh Intel sekitar era Pentium Pro, tetapi buggy dan tidak memberikan manfaat praktis). Jadi sistem Linux 32-bit modern benar-benar menggunakanSYSENTER
, bukanint 0x80
. - Kernel Linux x86 64-bit sebenarnya tidak menggunakan
SYSENTER
danSYSEXIT
. Mereka sebenarnya menggunakanSYSCALL
yang sangat mirip /SYSRET
instruksi.
Seperti yang ditunjukkan di komentar, SYSENTER
tidak benar-benar bekerja pada banyak sistem Linux 64-bit —yaitu AMD 64-bit sistem.
Ini memang situasi yang membingungkan. Detailnya ada di sini, tapi intinya adalah ini:
Untuk kernel 32bit, SYSENTER/SYSEXIT adalah satu-satunya pasangan yang kompatibel [antara CPU AMD dan Intel]
Untuk kernel 64bit dalam mode Panjang saja… SYSCALL/SYSRET adalah satu-satunya pasangan yang kompatibel [antara CPU AMD dan Intel]
Tampaknya pada Intel CPU dalam mode 64-bit, Anda dapat menggunakan SYSENTER
karena melakukan hal yang sama seperti SYSCALL
, namun ini tidak berlaku untuk sistem AMD.
Intinya:selalu gunakan SYSCALL
di Linux pada sistem x86 64-bit . Itulah yang sebenarnya ditentukan oleh x86-64 ABI. (Lihat jawaban wiki yang bagus ini untuk detail lebih lanjut.)