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 Konvensi Sistem Panggilan i386 Linux:
Dalam x86-32, parameter untuk panggilan sistem Linux dilewatkan menggunakan register. %eax
untuk syscall_number. % ebx,% ecx,% edx,% esi,% edi,% ebp digunakan untuk melewatkan 6 parameter ke panggilan sistem.
Nilai kembali dalam %eax
. Semua register lain (termasuk EFLAGS) dilestarikan di seluruh int $0x80
.
Saya mengikuti cuplikan dari Tutorial Perakitan Linux tapi saya ragu tentang ini. Jika ada yang bisa menunjukkan contoh, itu akan bagus.
Jika ada lebih dari enam argumen,
%ebx
harus berisi lokasi memori tempat daftar argumen disimpan - tetapi jangan khawatir tentang ini karena tidak mungkin 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 dari Hello World untuk i386 Linux menggunakan int 0x80
: Halo, dunia dalam bahasa assembly dengan panggilan sistem Linux?
Ada cara yang lebih cepat untuk melakukan panggilan sistem 32-bit: menggunakan sysenter
. Kernel memetakan satu halaman memori ke dalam setiap proses (vDSO), dengan sisi ruang pengguna dari sysenter
tarian, yang harus bekerja sama dengan kernel agar dapat menemukan alamat pengirim. Arg untuk mendaftarkan pemetaan sama dengan untuk int $0x80
. Anda biasanya harus memanggil ke vDSO daripada menggunakan sysenter
secara langsung. (Lihat Panduan Definitif untuk Panggilan Sistem Linux untuk info tentang menautkan dan memanggil ke vDSO, dan untuk info lebih lanjut tentang sysenter
, dan segala sesuatu yang berkaitan dengan panggilan sistem.)
x86-32 [Gratis | Buka | Net | DragonFly] Konvensi Sistem Panggilan BSD UNIX:
Parameter dilewatkan pada tumpukan. Dorong parameter (parameter terakhir didorong pertama) ke stack. Kemudian dorong data dummy 32-bit tambahan (Ini sebenarnya bukan data dummy. Lihat tautan berikut untuk info lebih lanjut) dan kemudian berikan instruksi panggilan sistemint $0x80
http://www.int80h.org/bsdasm/#default-calling-convention
Konvensi Sistem Panggilan Linux x86-64:
x86-64 Mac OS X serupa tetapi berbeda . TODO: periksa apa yang * BSD lakukan.
Lihat bagian: "A.2 Konvensi K64 Linux AMD64 " dari Aplikasi Sistem V Antarmuka Biner Tambahan Prosesor Arsitektur AMD64 . Versi terbaru dari Sistem i386 dan x86-64 psABI dapat ditemukan ditautkan dari halaman ini di repo pengelola ABI . (Lihat jugax86 beri tag wiki untuk tautan ABI terbaru dan banyak hal bagus lainnya tentang as x86.)
Berikut cuplikan dari bagian ini:
- Aplikasi tingkat pengguna digunakan sebagai register integer untuk melewatkan urutan% rdi,% rsi,% rdx,% rcx,% r8 dan% r9. Antarmuka kernel menggunakan% rdi,% rsi,% rdx,% r10,% r8 dan% r9.
- Panggilan sistem dilakukan melalui
syscall
instruksi . Clobbers ini % rcx dan% r11 serta nilai pengembalian % rax , tetapi register lain dipertahankan.
- Jumlah syscall harus diteruskan dalam register% rax.
- Panggilan sistem dibatasi hingga enam argumen, tidak ada argumen yang diteruskan langsung ke stack.
- Kembali dari syscall, register% rax berisi hasil dari system-call. Nilai dalam kisaran antara -4095 dan -1 menunjukkan kesalahan
-errno
.
- Hanya nilai class INTEGER atau MEMORY kelas 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
ABI 32-bit ini dapat digunakan dalam kode 64-bit (tapi sangat tidak disarankan). Apa yang terjadi jika Anda menggunakan ABI 32-bit int 0x80 Linux dalam kode 64-bit? Itu masih memotong inputnya ke 32-bit, jadi itu tidak cocok untuk pointer, dan itu nol r8-r11.
Antarmuka Pengguna: pemanggilan fungsi
Konvensi Fungsi Memanggil x86-32:
Dalam x86-32 parameter diteruskan pada stack. Parameter terakhir didorong pertama ke stack sampai semua parameter dilakukan dan kemudian call
instruksi dieksekusi. Ini digunakan untuk memanggil fungsi C library (libc) di Linux dari assembly.
Versi modern dari System V ABI i386 (digunakan pada Linux) memerlukan perataan 16 byte %esp
sebelum call
, seperti Sistem V86 AB86 x86 yang selalu diperlukan. Calle diizinkan untuk mengasumsikan itu dan menggunakan beban / toko SSE 16 byte yang gagal pada unaligned. Tetapi secara historis, Linux hanya membutuhkan 4-byte stack alignment, sehingga butuh kerja ekstra untuk memesan ruang yang rata-rata bahkan untuk 8-byte double
atau sesuatu.
Beberapa sistem 32-bit modern lainnya masih tidak memerlukan lebih dari 4 byte stack alignment.
x86-64 Konvensi pengguna-ruang System V: Panggilan Fungsi:
x86-64 System V melewatkan args dalam register, yang lebih efisien daripada konvensi stack args i386 System V. Ini menghindari latensi dan instruksi tambahan menyimpan args ke memori (cache) dan kemudian memuatnya kembali di callee. Ini bekerja dengan baik karena ada lebih banyak register yang tersedia, dan lebih baik untuk CPU berkinerja tinggi modern di mana masalah latensi dan eksekusi tidak sesuai pesanan. (ABI i386 sudah sangat tua).
Dalam mekanisme baru ini : Pertama parameter dibagi ke dalam kelas. Kelas dari setiap parameter menentukan cara di mana ia dilewatkan ke fungsi yang dipanggil.
Untuk informasi lengkap, lihat: "3.2 Urutan Pemanggilan Fungsi" dari Aplikasi Sistem V Antarmuka Biner Tambahan Prosesor Arsitektur AMD64 yang berbunyi, sebagian:
Setelah argumen diklasifikasikan, register ditugaskan (dalam urutan kiri-ke-kanan) untuk diteruskan sebagai berikut:
- Jika kelas adalah MEMORY, sampaikan argumen pada stack.
- Jika kelas 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 agar digunakan untuk melewati bilangan bulat / pointer (yaitu INTEGER kelas) parameter ke fungsi libc dari perakitan. % rdi digunakan untuk parameter INTEGER pertama. % rsi untuk ke-2,% rdx untuk ke-3 dan seterusnya. Maka call
instruksi harus diberikan. Stack ( %rsp
) harus sejajar 16B saat call
dijalankan.
Jika ada lebih dari 6 parameter INTEGER, parameter INTEGER ke-7 dan yang lebih baru dilewatkan pada stack. (Pemanggil muncul, sama seperti x86-32.)
8 argumen floating point pertama dilewatkan dalam% xmm0-7, nanti di stack. Tidak ada register vektor yang diawetkan dengan panggilan. (Fungsi dengan campuran argumen FP dan integer dapat memiliki lebih dari 8 argumen register total.)
Fungsi variadik ( sepertiprintf
) selalu membutuhkan %al
= jumlah argumen register FP.
Ada aturan untuk kapan memasukkan paket ke register ( rdx:rax
saat kembali) vs. dalam memori. Lihat ABI untuk detailnya, dan periksa output kompiler untuk memastikan kode Anda setuju dengan kompiler tentang bagaimana sesuatu harus dilewatkan / dikembalikan.
Perhatikan bahwa konvensi pemanggilan fungsi Windows x64 memiliki beberapa perbedaan signifikan dari Sistem x86-64, seperti ruang bayangan yang harus dipesan oleh penelepon (bukan zona merah), dan xmm6-xmm15 yang dipelihara dengan panggilan. Dan aturan yang sangat berbeda untuk arg mana masuk register.