GNU/Linux >> Belajar Linux >  >> Linux

Apa konvensi pemanggilan untuk panggilan sistem UNIX &Linux (dan fungsi ruang pengguna) pada i386 dan x86-64

Bacaan lebih lanjut untuk topik apa pun di sini:Panduan Definitif untuk Panggilan Sistem Linux

Saya memverifikasi ini menggunakan GNU Assembler (gas) di Linux.

Antarmuka Kernel

x86-32 alias i386 Konvensi Panggilan Sistem Linux:

Dalam parameter x86-32 untuk panggilan sistem Linux dilewatkan menggunakan register. %eax untuk syscall_number. %ebx, %ecx, %edx, %esi, %edi, %ebp digunakan untuk meneruskan 6 parameter ke panggilan sistem.

Nilai yang dikembalikan ada di %eax . Semua register lain (termasuk EFLAGS) disimpan di seluruh int $0x80 .

Saya mengambil cuplikan berikut dari Tutorial Perakitan Linux tetapi saya ragu tentang ini. Jika ada yang bisa menunjukkan contoh, itu akan sangat bagus.

Jika ada lebih dari enam argumen,%ebx harus berisi lokasi memori tempat daftar argumen disimpan - tetapi jangan khawatir tentang hal ini karena kecil kemungkinannya Anda akan menggunakan syscall dengan lebih dari enam argumen.

Untuk contoh dan bacaan lebih lanjut, lihat http://www.int80h.org/bsdasm/#alternate-calling-convention. Contoh lain Hello World untuk i386 Linux menggunakan int 0x80 :Halo, dunia dalam bahasa rakitan dengan panggilan sistem Linux?

Ada cara yang lebih cepat untuk melakukan panggilan sistem 32-bit:menggunakan sysenter . Kernel memetakan halaman memori ke dalam setiap proses (vDSO), dengan sisi ruang pengguna dari sysenter dance, yang harus bekerja sama dengan kernel agar dapat menemukan alamat pengirim. Arg untuk mendaftarkan pemetaan sama dengan int $0x80 . Biasanya Anda harus memanggil vDSO alih-alih menggunakan sysenter secara langsung. (Lihat Panduan Definitif untuk Panggilan Sistem Linux untuk info tentang penautan dan panggilan ke vDSO, dan untuk info lebih lanjut tentang sysenter , dan hal lain yang berkaitan dengan panggilan sistem.)

x86-32 [Gratis|Buka|Net|DragonFly]Konvensi Panggilan Sistem UNIX BSD:

Parameter dilewatkan pada stack. Dorong parameter (parameter terakhir didorong lebih dulu) ke tumpukan. Kemudian Dorong data tiruan 32-bit tambahan (Ini sebenarnya bukan data tiruan. Lihat tautan berikut untuk info lebih lanjut) dan kemudian berikan instruksi panggilan sistem int $0x80

http://www.int80h.org/bsdasm/#default-calling-convention

x86-64 Konvensi Panggilan Sistem Linux:

(Catatan:x86-64 Mac OS X mirip tetapi berbeda dari Linux. TODO:periksa apa yang *BSD lakukan)

Lihat bagian:"A.2 AMD64 Linux Kernel Conventions" dari System V Application Binary Interface Tambahan Prosesor Arsitektur AMD64. Versi terbaru psABI System V i386 dan x86-64 dapat ditemukan ditautkan dari halaman ini di repo pengelola ABI. (Lihat juga wiki tag x86 untuk up- tautan ABI terkini dan banyak hal bagus lainnya tentang x86 asm.)

Ini cuplikan dari bagian ini:

  1. Aplikasi tingkat pengguna digunakan sebagai register bilangan bulat untuk meneruskan urutan %rdi, %rsi, %rdx, %rcx,%r8, dan %r9. Antarmuka kernel menggunakan %rdi, %rsi, %rdx, %r10, %r8 dan %r9.
  2. Panggilan sistem dilakukan melalui syscall instruksi . Ini mengalahkan %rcx dan %r11 serta nilai kembalian %rax, tetapi register lain dipertahankan.
  3. Nomor syscall harus diteruskan dalam register %rax.
  4. System-call dibatasi hingga enam argumen, tidak ada argumen yang diteruskan langsung ke stack.
  5. Kembali dari syscall, register %rax berisi hasil dari system-call. Nilai dalam kisaran antara -4095 dan -1 menunjukkan kesalahan, yaitu -errno .
  6. Hanya nilai kelas INTEGER atau kelas MEMORY yang diteruskan ke kernel.

Ingat ini dari lampiran khusus Linux ke ABI, dan bahkan untuk Linux itu informatif bukan normatif. (Tapi itu sebenarnya akurat.)

int $0x80 32-bit ini ABI adalah dapat digunakan dalam kode 64-bit (tetapi sangat tidak disarankan). Apa yang terjadi jika Anda menggunakan ABI Linux 32-bit int 0x80 dalam kode 64-bit? Itu masih memotong inputnya menjadi 32-bit, jadi tidak cocok untuk pointer, dan nol r8-r11.

Antarmuka Pengguna:pemanggilan fungsi

Konvensi Pemanggilan Fungsi x86-32:

Dalam parameter x86-32 diteruskan ke tumpukan. Parameter terakhir didorong terlebih dahulu ke tumpukan sampai semua parameter selesai dan kemudian call instruksi dieksekusi. Ini digunakan untuk memanggil fungsi pustaka C (libc) di Linux dari rakitan.

Versi modern dari i386 System V ABI (digunakan di Linux) memerlukan penyelarasan 16-byte dari %esp sebelum call , seperti x86-64 System V ABI yang selalu dibutuhkan. Callees diizinkan untuk mengasumsikan itu dan menggunakan beban/penyimpanan SSE 16-byte yang salah pada yang tidak selaras. Namun secara historis, Linux hanya membutuhkan penyelarasan tumpukan 4-byte, jadi butuh kerja ekstra untuk memesan ruang yang selaras secara alami bahkan untuk double 8-byte atau sesuatu.

Beberapa sistem 32-bit modern lainnya masih tidak memerlukan penyelarasan tumpukan lebih dari 4 byte.

konvensi Pemanggilan Fungsi ruang-pengguna Sistem V x86-64:

x86-64 System V melewatkan argumen dalam register, yang lebih efisien daripada konvensi stack args Sistem V i386. Itu menghindari latensi dan instruksi tambahan untuk menyimpan argumen ke memori (cache) dan kemudian memuatnya kembali di callee. Ini berfungsi dengan baik karena ada lebih banyak register yang tersedia, dan lebih baik untuk CPU modern berperforma tinggi di mana masalah latensi dan eksekusi tidak sesuai urutan. (ABI i386 sudah sangat tua).

Di baru ini mekanisme:Pertama parameter dibagi ke dalam kelas. Kelas setiap parameter menentukan cara penerusannya ke fungsi yang dipanggil.

Untuk informasi selengkapnya lihat :"3.2 Function Calling Sequence" dari System V Application Binary Interface Suplemen Prosesor Arsitektur AMD64 yang berbunyi, sebagian:

Setelah argumen diklasifikasikan, register ditugaskan (urutan kiri ke kanan) untuk diteruskan sebagai berikut:

  1. Jika kelasnya adalah MEMORY, teruskan argumen pada tumpukan.
  2. Jika kelasnya adalah INTEGER, register berikutnya yang tersedia dari urutan %rdi, %rsi, %rdx, %rcx, %r8 dan %r9 digunakan

Jadi %rdi, %rsi, %rdx, %rcx, %r8 and %r9 adalah register berurutan digunakan untuk meneruskan parameter integer/pointer (yaitu kelas INTEGER) ke fungsi libc apa pun dari rakitan. %rdi digunakan untuk parameter INTEGER pertama. %rsi untuk ke-2, %rdx untuk ke-3 dan seterusnya. Lalu call instruksi harus diberikan. Tumpukan (%rsp ) harus selaras 16B saat call mengeksekusi.

Jika ada lebih dari 6 parameter INTEGER, parameter INTEGER ke-7 dan yang lebih baru akan diteruskan ke stack. (Penelepon muncul, sama seperti x86-32.)

8 arg floating point pertama diteruskan di %xmm0-7, nanti di stack. Tidak ada register vektor yang diawetkan oleh panggilan. (Fungsi dengan campuran FP dan argumen bilangan bulat dapat memiliki lebih dari 8 total argumen register.)

Fungsi variabel (seperti printf ) selalu membutuhkan %al =jumlah argumen register FP.

Ada aturan kapan mengemas struct ke dalam register (rdx:rax saat kembali) vs. dalam memori. Lihat ABI untuk detailnya, dan periksa keluaran kompiler untuk memastikan kode Anda setuju dengan kompiler tentang bagaimana sesuatu harus diteruskan/dikembalikan.

Perhatikan bahwa konvensi pemanggilan fungsi Windows x64 memiliki beberapa perbedaan signifikan dari x86-64 System V, seperti ruang bayangan yang harus dicadangkan oleh penelepon (bukan zona merah), dan xmm6-xmm15 yang dipertahankan oleh panggilan. Dan aturan yang sangat berbeda untuk arg yang masuk ke register mana.


Mungkin Anda sedang mencari ABI x86_64?

  • www.x86-64.org/documentation/abi.pdf (404 pada 24-11-2018)
  • www.x86-64.org/documentation/abi.pdf (melalui Wayback Machine pada 24-11-2018)
  • Di mana x86-64 System V ABI didokumentasikan? - https://github.com/hjl-tools/x86-psABI/wiki/X86-psABI terus diperbarui (oleh HJ Lu, salah satu pengelola ABI) dengan tautan ke PDF dari versi resmi saat ini.

Jika bukan itu yang Anda cari, gunakan 'x86_64 abi' di mesin telusur pilihan Anda untuk menemukan referensi alternatif.


Konvensi pemanggilan menentukan bagaimana parameter dilewatkan dalam register saat memanggil atau dipanggil oleh program lain. Dan sumber terbaik dari konvensi ini adalah dalam bentuk standar ABI yang ditentukan untuk masing-masing perangkat keras tersebut. Untuk kemudahan kompilasi, ABI yang sama juga digunakan oleh userspace dan program kernel. Linux/Freebsd mengikuti ABI yang sama untuk x86-64 dan set lain untuk 32-bit. Tetapi x86-64 ABI untuk Windows berbeda dari Linux/FreeBSD. Dan umumnya ABI tidak membedakan panggilan sistem vs "panggilan fungsi" normal. Yaitu, berikut adalah contoh khusus konvensi pemanggilan x86_64 dan itu sama untuk ruang pengguna dan kernel Linux:http://eli.thegreenplace.net/2011/ 09/06/stack-frame-layout-on-x86-64/ (perhatikan urutan parameter a,b,c,d,e,f):

Performa adalah salah satu alasan ABI ini (misalnya, meneruskan parameter melalui register, bukan menyimpan ke tumpukan memori)

Untuk ARM ada berbagai ABI:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.abi/index.html

https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/iPhoneOSABIReference.pdf

Konvensi ARM64:

http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf

Untuk Linux di PowerPC:

http://refspecs.freestandards.org/elf/elfspec_ppc.pdf

http://www.0x04.net/doc/elf/psABI-ppc64.pdf

Dan untuk embedded ada PPC EABI:

http://www.freescale.com/files/32bit/doc/app_note/PPCEABI.pdf

Dokumen ini adalah ikhtisar yang baik dari semua konvensi yang berbeda:

http://www.agner.org/optimize/calling_conventions.pdf


Linux
  1. Apa Karakter Khusus Dan Blokir File Khusus Dalam Sistem Unix??

  2. Apa buku Linux/Unix yang bagus untuk pengguna tingkat lanjut?

  3. Apa antarmuka untuk panggilan sistem ARM dan di mana itu didefinisikan dalam kernel Linux?

  1. Apa panggilan OS / sistem asli Windows dan Linux yang dibuat dari malloc ()?

  2. berapa panjang maksimal kata sandi pada sistem unix/linux?

  3. Linux top command:Apa kita, sy, ni, id, wa, hi, si dan st (untuk penggunaan CPU)?

  1. Linux vs. Unix:Apa bedanya?

  2. Berapa jumlah ruang swap yang tepat untuk sistem Linux modern?

  3. Apa perbedaan antara Unix, Linux, BSD dan GNU?