Mengapa Windows64 menggunakan konvensi panggilan yang berbeda dari semua OS lain di x86-64?

110

AMD memiliki spesifikasi ABI yang menjelaskan konvensi pemanggilan untuk digunakan pada x86-64. Semua OS mengikutinya, kecuali untuk Windows yang memiliki konvensi pemanggilan x86-64 sendiri. Mengapa?

Adakah yang tahu alasan teknis, sejarah, atau politik untuk perbedaan ini, atau apakah ini murni masalah NIHsyndrome?

Saya memahami bahwa OS yang berbeda mungkin memiliki kebutuhan yang berbeda untuk hal-hal tingkat yang lebih tinggi, tetapi itu tidak menjelaskan mengapa misalnya parameter register yang meneruskan urutan pada Windows adalah rcx - rdx - r8 - r9 - rest on stacksementara orang lain menggunakan rdi - rsi - rdx - rcx - r8 - r9 - rest on stack.

NB Saya mengetahui bagaimana perbedaan konvensi panggilan ini secara umum dan saya tahu di mana menemukan detailnya jika perlu. Yang ingin saya ketahui adalah mengapa .

Edit: untuk caranya, lihat misalnya entri wikipedia dan link dari sana.

JanKanis
sumber
2
Nah, hanya untuk register pertama: rcx: ecx adalah parameter "ini" untuk konvensi msvc __thiscall x86. Jadi mungkin hanya untuk memudahkan porting compiler mereka ke x64, mereka memulai dengan rcx sebagai yang pertama. Bahwa segala sesuatu yang lain kemudian akan berbeda juga hanyalah konsekuensi dari keputusan awal itu.
Chris Becke
@ Chris: Saya telah menambahkan referensi ke dokumen suplemen ABI AMD64 (dan beberapa penjelasan apa sebenarnya itu) di bawah.
FrankH.
1
Saya belum menemukan alasan dari MS tetapi saya menemukan beberapa diskusi di sini
phuclv

Jawaban:

81

Memilih empat register argumen pada x64 - umum untuk UN * X / Win64

Salah satu hal yang perlu diingat tentang x86 adalah bahwa nama register untuk pengkodean "reg number" tidak jelas; dalam hal pengkodean instruksi ( MOD R / M byte, lihat http://www.c-jump.com/CIS77/CPU/x86/X77_0060_mod_reg_r_m_byte.htm ), nomor register 0 ... 7 adalah - dalam urutan itu - ?AX, ?CX, ?DX, ?BX, ?SP, ?BP, ?SI, ?DI.

Oleh karena itu memilih A / C / D (regs 0..2) untuk nilai kembalian dan dua argumen pertama (yang merupakan __fastcallkonvensi 32bit "klasik" ) adalah pilihan yang logis. Sejauh menyangkut 64bit, regs "lebih tinggi" dipesan, dan baik Microsoft dan UN * X / Linux menggunakan R8/ R9sebagai yang pertama.

Menjaga bahwa dalam pikiran, pilihan Microsoft RAX(nilai kembali) dan RCX, RDX, R8, R9(arg [0..3]) adalah pilihan yang dimengerti jika Anda memilih empat register untuk argumen.

Saya tidak tahu mengapa memilih AMD64 UN * X ABI RDXsebelumnya RCX.

Memilih enam register argumen pada x64 - spesifik UN * X

UN * X, pada arsitektur RISC, secara tradisional melakukan penyampaian argumen dalam register - khususnya, untuk enam argumen pertama (demikian pula pada PPC, SPARC, MIPS setidaknya). Yang mungkin menjadi salah satu alasan utama mengapa desainer ABI AMD64 (UN * X) memilih untuk menggunakan enam register pada arsitektur itu juga.

Jadi jika Anda ingin enam register untuk melewati argumen di, dan itu logis untuk memilih RCX, RDX, R8dan R9empat dari mereka, yang dua lainnya harus Anda pilih?

Regs "lebih tinggi" memerlukan byte awalan instruksi tambahan untuk memilihnya dan karena itu memiliki footprint ukuran instruksi yang lebih besar, jadi Anda tidak ingin memilih salah satu dari itu jika Anda memiliki opsi. Dari register klasik, karena arti implisitRBP dan RSPini tidak tersedia, dan secara RBXtradisional memiliki penggunaan khusus pada UN * X (tabel offset global) yang tampaknya tidak diinginkan oleh desainer AMD64 ABI untuk menjadi tidak kompatibel.
Ergo, satu - satunya pilihan adalah RSI/ RDI.

Jadi jika Anda harus mengambil RSI/ RDIsebagai register argumen, argumen mana yang seharusnya?

Membuatnya arg[0]dan arg[1]memiliki beberapa keuntungan. Lihat komentar cHao.
?SIdan ?DImerupakan operan sumber / tujuan instruksi string, dan seperti yang disebutkan cHao, penggunaannya sebagai register argumen berarti bahwa dengan konvensi pemanggilan AMD64 UN * X, fungsi yang paling sederhana strcpy(), misalnya, hanya terdiri dari dua instruksi CPU repz movsb; retkarena sumber / target alamat telah dimasukkan ke register yang benar oleh pemanggil. Ada, khususnya dalam kode "perekat" tingkat rendah dan yang dihasilkan compiler (pikirkan, misalnya, beberapa pengalokasi heap C ++ objek pengisian nol pada konstruksi, atau halaman heap pengisian-nol kernel padasbrk(), atau copy-on-write pagefaults) sejumlah besar salinan / isi blok, oleh karena itu akan berguna untuk kode yang sering digunakan untuk menyimpan dua atau tiga instruksi CPU yang sebaliknya memuat argumen alamat sumber / target ke dalam register yang "benar".

Jadi dengan cara, PBB * X dan Win64 hanya berbeda dalam bahwa PBB * X "prepends" dua argumen tambahan, di sengaja dipilih RSI/ RDIregister, dengan pilihan alami dari empat argumen di RCX, RDX, R8dan R9.

Lebih dari itu ...

Ada lebih banyak perbedaan antara UN * X dan Windows x64 ABI daripada hanya pemetaan argumen ke register tertentu. Untuk gambaran umum tentang Win64, periksa:

http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx

Win64 dan AMD64 UN * X juga sangat berbeda dalam cara penggunaan stackspace; di Win64, misalnya, pemanggil harus mengalokasikan stackspace untuk argumen fungsi meskipun argumen 0 ... 3 diteruskan dalam register. Di UN * X di sisi lain, fungsi daun (yaitu yang tidak memanggil fungsi lain) bahkan tidak diperlukan untuk mengalokasikan stackspace sama sekali jika dibutuhkan tidak lebih dari 128 Byte (ya, Anda memiliki dan dapat menggunakan sejumlah tumpukan tertentu tanpa mengalokasikannya ... yah, kecuali Anda adalah kode kernel, sumber bug bagus). Semua ini adalah pilihan pengoptimalan khusus, sebagian besar alasan untuk itu dijelaskan dalam referensi ABI lengkap yang dirujuk oleh referensi wikipedia poster asli.

FrankH.
sumber
1
Tentang nama register: Byte awalan itu mungkin merupakan faktor. Tetapi akan lebih logis bagi MS untuk memilih rcx - rdx - rdi - rsi sebagai register argumen. Tetapi nilai numerik dari delapan yang pertama dapat memandu Anda jika Anda mendesain ABI dari awal, tetapi tidak ada alasan untuk mengubahnya jika ABI yang sangat bagus sudah ada, yang hanya akan menimbulkan lebih banyak kebingungan.
JanKanis
2
Di RSI / RDI: Petunjuk ini biasanya akan sebaris, dalam hal ini konvensi pemanggilan tidak menjadi masalah. Jika tidak, hanya ada satu salinan (atau mungkin beberapa) dari fungsi tersebut di seluruh sistem, sehingga hanya menghemat beberapa byte secara total . Tidak layak. Pada perbedaan lain / tumpukan panggilan: Kegunaan pilihan tertentu dijelaskan dalam referensi ABI, tetapi mereka tidak membuat perbandingan. Mereka tidak mengatakan mengapa pengoptimalan lain tidak dipilih - misalnya mengapa Windows tidak memiliki zona merah 128 byte, dan mengapa AMD ABI tidak memiliki slot tumpukan tambahan untuk argumen?
JanKanis
1
@cHao: tidak. Tapi mereka tetap mengubahnya. Win64 ABI berbeda dari Win32 (dan tidak kompatibel), dan juga berbeda dari AMD ABI.
JanKanis
7
@Somejan: Win64 dan Win32 __fastcall100% identik jika tidak lebih dari dua argumen yang tidak lebih dari 32bit dan mengembalikan nilai tidak lebih dari 32bit. Itu bukan kelas fungsi yang kecil. Tidak ada kompatibilitas mundur seperti itu sama sekali yang mungkin antara UN * X ABI untuk i386 / amd64.
FrankH.
2
@szx: Saya baru saja menemukan utas milis yang relevan dari November 2000, dan memposting jawaban yang merangkum alasannya. Perhatikan bahwa itu memcpybisa diterapkan seperti itu, bukan strcpy.
Peter Cordes
42

IDK mengapa Windows melakukan apa yang mereka lakukan. Lihat akhir dari jawaban ini untuk menebak. Saya ingin tahu tentang bagaimana konvensi panggilan SysV diputuskan, jadi saya menggali arsip milis dan menemukan beberapa hal yang rapi.

Menarik sekali membaca beberapa utas lama di milis AMD64, karena arsitek AMD aktif di dalamnya. misalnya Memilih nama register adalah salah satu bagian yang sulit: AMD mempertimbangkan untuk mengganti nama asli 8 register r0-r7, atau memanggil register baru sepertiUAX .

Juga, umpan balik dari pengembang kernel mengidentifikasi hal-hal yang membuat desain asli syscalldan swapgstidak dapat digunakan . Begitulah cara AMD memperbarui instruksi untuk menyelesaikan ini sebelum merilis chip yang sebenarnya. Menarik juga bahwa di akhir tahun 2000, ada anggapan bahwa Intel mungkin tidak akan mengadopsi AMD64.


Konvensi pemanggilan SysV (Linux), dan keputusan tentang berapa banyak register yang harus dipertahankan-callee vs. caller-save, awalnya dibuat pada November 2000, oleh Jan Hubicka (pengembang gcc). Dia mengumpulkan SPEC2000 dan melihat ukuran kode dan jumlah instruksi. Utas diskusi itu memantulkan beberapa ide yang sama dengan jawaban dan komentar atas pertanyaan SO ini. Di thread ke-2, dia mengusulkan urutan saat ini sebagai yang optimal dan semoga final, menghasilkan kode yang lebih kecil daripada beberapa alternatif .

Dia menggunakan istilah "global" yang berarti register dengan panggilan yang dipertahankan, yang harus di-push / pop jika digunakan.

Pilihan rdi, rsi, rdxsebagai tiga args pertama didorong oleh:

  • penghematan ukuran kode kecil dalam fungsi yang memanggil memsetatau fungsi string C lainnya pada args mereka (di mana gcc mengaitkan operasi string rep?)
  • rbxdipertahankan panggilan karena memiliki dua reg yang dipertahankan panggilan dapat diakses tanpa awalan REX (rbx dan rbp) adalah kemenangan. Mungkin dipilih karena itu satu-satunya reg lain yang tidak secara implisit digunakan oleh instruksi apa pun. (string rep, hitungan shift, dan output / input mul / div menyentuh yang lainnya).
  • Tak satu pun dari register dengan tujuan khusus dipertahankan panggilan (lihat poin sebelumnya), jadi fungsi yang ingin menggunakan instruksi string rep atau pergeseran jumlah variabel mungkin harus memindahkan argumen fungsi ke tempat lain, tetapi tidak harus menyimpan / mengembalikan nilai pemanggil.
  • Kami mencoba untuk menghindari RCX di awal urutan, karena ini adalah register yang biasa digunakan untuk keperluan khusus, seperti EAX, jadi memiliki tujuan yang sama untuk tidak ada di urutan. Juga tidak dapat digunakan untuk syscall dan kami ingin membuat urutan syscall untuk mencocokkan urutan pemanggilan fungsi sebanyak mungkin.

    (latar belakang: syscall/ sysretmenghancurkan rcx(dengan rip) dan r11(dengan RFLAGS), sehingga kernel tidak dapat melihat apa yang semula berada rcxsaat syscalldijalankan.)

ABI panggilan sistem kernel dipilih untuk mencocokkan panggilan fungsi ABI, kecuali sebagai r10gantinya rcx, jadi pembungkus libc berfungsi seperti mmap(2)can just mov %rcx, %r10/ mov $0x9, %eax/ syscall.


Perhatikan bahwa konvensi pemanggilan SysV yang digunakan oleh i386 Linux payah dibandingkan dengan 32bit __vectorcall dari Window. Ini meneruskan semua yang ada di tumpukan, dan hanya mengembalikan edx:eaxuntuk int64, bukan untuk struct kecil . Tidak mengherankan jika sedikit usaha dilakukan untuk menjaga kompatibilitas dengannya. Ketika tidak ada alasan untuk tidak melakukannya, mereka melakukan hal-hal seperti menjagarbx panggilan dipertahankan, karena mereka memutuskan bahwa memiliki yang lain di 8 asli (yang tidak memerlukan awalan REX) itu bagus.

Menjadikan ABI optimal untuk jangka panjang jauh lebih penting daripada pertimbangan lainnya. Saya pikir mereka melakukan pekerjaan yang cukup baik. Saya tidak sepenuhnya yakin tentang mengembalikan struct yang dikemas ke dalam register, alih-alih bidang yang berbeda di reg yang berbeda. Saya kira kode yang menyebarkan mereka berdasarkan nilai tanpa benar-benar beroperasi di ladang menang dengan cara ini, tetapi pekerjaan ekstra untuk membongkar tampak konyol. Mereka dapat memiliki lebih banyak register pengembalian integer, lebih dari sekedar rdx:rax, jadi mengembalikan struct dengan 4 anggota dapat mengembalikannya dalam rdi, rsi, rdx, rax atau sesuatu.

Mereka mempertimbangkan untuk melewatkan bilangan bulat dalam reg vektor, karena SSE2 dapat beroperasi pada bilangan bulat. Untungnya mereka tidak melakukan itu. Bilangan bulat sangat sering digunakan sebagai offset penunjuk, dan perjalanan pulang-pergi ke memori stack cukup murah . Juga instruksi SSE2 mengambil lebih banyak byte kode daripada instruksi integer.


Saya menduga perancang Windows ABI mungkin bertujuan untuk meminimalkan perbedaan antara 32 dan 64bit untuk kepentingan orang-orang yang harus mem-port asm dari satu ke yang lain, atau yang dapat menggunakan pasangan #ifdefdalam beberapa ASM sehingga sumber yang sama dapat lebih mudah dibangun versi 32 atau 64bit dari suatu fungsi.

Meminimalkan perubahan dalam toolchain sepertinya tidak mungkin. Kompiler x86-64 memerlukan tabel terpisah yang registernya digunakan untuk apa, dan apa konvensi pemanggilannya. Memiliki sedikit tumpang tindih dengan 32bit tidak mungkin menghasilkan penghematan yang signifikan dalam ukuran / kompleksitas kode toolchain.

Peter Cordes
sumber
1
Saya rasa saya telah membaca di suatu tempat di blog Raymond Chen tentang alasan memilih register tersebut setelah benchmarking dari sisi MS tetapi saya tidak dapat menemukannya lagi. Namun beberapa alasan mengenai homezone itu dijelaskan di sini blogs.msdn.microsoft.com/oldnewthing/20160623-00/?p=93735 blogs.msdn.microsoft.com/freik/2006/03/06/...
phuclv
@phuclv: Lihat juga Apakah valid untuk menulis di bawah ESP? . Komentar Raymond tentang jawaban saya di sana menunjukkan beberapa detail SEH yang saya tidak tahu yang menjelaskan mengapa x86 32/64 Windows saat ini tidak memiliki zona merah de-facto. Posting blognya memiliki beberapa kasus yang masuk akal untuk kemungkinan penangan halaman kode yang sama yang saya sebutkan dalam jawaban itu :) Jadi ya, Raymond melakukan pekerjaan yang lebih baik dalam menjelaskannya daripada yang saya lakukan (tidak mengejutkan karena saya mulai dari mengetahui sangat sedikit tentang Windows), dan tabel ukuran zona merah untuk non-x86 benar-benar rapi.
Peter Cordes
13

Ingatlah bahwa Microsoft pada awalnya "secara resmi tidak berkomitmen terhadap upaya awal AMD64" (dari "A History of Modern 64-bit Computing" oleh Matthew Kerner dan Neil Padgett) karena mereka adalah mitra yang kuat dengan Intel dalam arsitektur IA64. Saya pikir ini berarti bahwa meskipun mereka akan terbuka untuk bekerja dengan insinyur GCC pada ABI untuk digunakan pada Unix dan Windows, mereka tidak akan melakukannya karena itu berarti secara terbuka mendukung upaya AMD64 ketika mereka tidak melakukannya. t belum resmi melakukannya (dan mungkin akan mengecewakan Intel).

Selain itu, pada masa itu Microsoft sama sekali tidak bersahabat dengan proyek open source. Tentu bukan Linux atau GCC.

Jadi mengapa mereka bekerja sama dalam ABI? Saya rasa ABI berbeda hanya karena dirancang pada waktu yang kurang lebih sama dan dalam isolasi.

Kutipan lain dari "A History of Modern 64-bit Computing":

Sejalan dengan kolaborasi Microsoft, AMD juga melibatkan komunitas open source untuk mempersiapkan chip tersebut. AMD membuat kontrak dengan Code Sorcery dan SuSE untuk pekerjaan rantai alat (Red Hat telah dilibatkan oleh Intel pada port rantai alat IA64). Russell menjelaskan bahwa SuSE memproduksi kompiler C dan FORTRAN, dan Code Sorcery memproduksi kompiler Pascal. Weber menjelaskan, pihaknya juga terlibat dengan komunitas Linux untuk menyiapkan port Linux. Upaya ini sangat penting: ini bertindak sebagai insentif bagi Microsoft untuk terus berinvestasi dalam upaya AMD64 Windows, dan juga memastikan bahwa Linux, yang menjadi OS penting pada saat itu, akan tersedia setelah chip dirilis.

Lebih jauh Weber mengatakan bahwa pekerjaan Linux sangat penting bagi kesuksesan AMD64, karena memungkinkan AMD untuk memproduksi sistem ujung ke ujung tanpa bantuan perusahaan lain jika perlu. Kemungkinan ini memastikan bahwa AMD memiliki strategi bertahan hidup kasus terburuk bahkan jika mitra lain mundur, yang pada gilirannya membuat mitra lain tetap terlibat karena takut tertinggal.

Ini menunjukkan bahwa bahkan AMD tidak merasa bahwa kerjasama merupakan hal yang paling penting antara MS dan Unix, tetapi memiliki dukungan Unix / Linux sangatlah penting. Mungkin bahkan mencoba meyakinkan salah satu atau kedua belah pihak untuk berkompromi atau bekerja sama tidak sebanding dengan usaha atau risiko (?) Untuk menjengkelkan salah satu dari mereka? Mungkin AMD berpikir bahwa bahkan menyarankan ABI yang umum dapat menunda atau menggagalkan tujuan yang lebih penting dari sekadar menyiapkan dukungan perangkat lunak ketika chip sudah siap.

Spekulasi di pihak saya, tetapi saya pikir alasan utama ABI berbeda adalah alasan politik bahwa MS dan pihak Unix / Linux tidak bekerja sama di dalamnya, dan AMD tidak melihatnya sebagai masalah.

Michael Burr
sumber
Perspektif yang bagus tentang politik. Saya setuju bahwa itu bukan kesalahan atau tanggung jawab AMD. Saya menyalahkan Microsoft karena memilih konvensi panggilan yang lebih buruk. Jika konvensi panggilan mereka ternyata lebih baik, saya akan bersimpati, tetapi mereka harus mengubah dari ABI awal mereka menjadi __vectorcallkarena meneruskan __m128tumpukan itu payah. Memiliki semantik yang dipertahankan panggilan untuk 128b rendah dari beberapa reg vektor juga aneh (sebagian karena kesalahan Intel karena tidak merancang mekanisme simpan / pulihkan yang dapat diperluas dengan SSE aslinya, dan masih tidak dengan AVX.)
Peter Cordes
1
Saya tidak benar-benar memiliki keahlian atau pengetahuan tentang seberapa bagus ABI. Saya hanya sesekali perlu mengetahui apa itu agar saya dapat memahami / men-debug di tingkat perakitan.
Michael Burr
1
ABI yang baik meminimalkan ukuran kode dan jumlah instruksi, dan menjaga rantai ketergantungan tetap rendah latensi dengan menghindari perjalanan bolak-balik ekstra melalui memori. (untuk args, atau untuk penduduk lokal yang perlu ditumpahkan / diisi ulang). Ada pengorbanan. Zona merah SysV membutuhkan beberapa instruksi tambahan di satu tempat (dispatcher penangan sinyal kernel), untuk keuntungan yang relatif besar untuk fungsi daun karena tidak harus menyesuaikan penunjuk tumpukan untuk mendapatkan beberapa ruang awal. Jadi itu kemenangan yang jelas dengan downside mendekati nol. Itu diadopsi dengan hampir tidak ada diskusi setelah itu diusulkan untuk SysV.
Peter Cordes
1
@dgnuff: Benar, itulah jawaban untuk Mengapa kode kernel tidak bisa menggunakan Zona Merah . Interupsi menggunakan tumpukan kernel, bukan tumpukan ruang pengguna, bahkan jika mereka datang saat CPU menjalankan kode ruang pengguna. Kernel tidak mempercayai tumpukan ruang pengguna karena utas lain dalam proses ruang pengguna yang sama dapat memodifikasinya, sehingga mengambil alih kendali kernel!
Peter Cordes
1
@ DavidA.Gray: ya, ABI tidak mengatakan Anda harus menggunakan RBP sebagai penunjuk bingkai sehingga kode yang dioptimalkan biasanya tidak (kecuali dalam fungsi yang menggunakan allocaatau beberapa kasus lain). Ini normal jika Anda terbiasa menggunakan gcc -fomit-frame-pointerdefault di Linux. ABI mendefinisikan metadata stack-unwind yang memungkinkan penanganan pengecualian tetap berfungsi. (Saya berasumsi ini berfungsi seperti GNU / Linux x86-64 System V's CFI stuff in .eh_frame). gcc -fomit-frame-pointertelah menjadi default (dengan pengoptimalan diaktifkan) sejak selamanya di x86-64, dan kompiler lain (seperti MSVC) melakukan hal yang sama.
Peter Cordes
12

Win32 memiliki kegunaannya sendiri untuk ESI dan EDI, dan mengharuskan mereka tidak dimodifikasi (atau setidaknya dipulihkan sebelum memanggil ke API). Saya membayangkan kode 64-bit melakukan hal yang sama dengan RSI dan RDI, yang akan menjelaskan mengapa mereka tidak digunakan untuk meneruskan argumen fungsi.

Saya tidak bisa memberi tahu Anda mengapa RCX dan RDX diaktifkan.

cHao
sumber
1
Semua konvensi pemanggilan memiliki beberapa register yang ditunjuk sebagai awal dan beberapa dipertahankan seperti ESI / EDI dan RSI / RDI di Win64. Tetapi itu adalah register tujuan umum, Microsoft dapat memilih tanpa masalah untuk menggunakannya secara berbeda.
JanKanis
1
@Somejan: Tentu, jika mereka ingin menulis ulang seluruh API dan memiliki dua OS yang berbeda. Saya tidak akan menyebutnya "tanpa masalah". Selama puluhan tahun, MS telah membuat janji tertentu tentang apa yang akan dan tidak akan dilakukannya dengan register x86, dan mereka kurang lebih konsisten dan kompatibel sepanjang waktu. Mereka tidak akan membuang semua itu ke luar jendela hanya karena beberapa dekrit dari AMD, terutama yang sangat sewenang-wenang dan di luar bidang "membangun prosesor".
cHao
5
@Somejan: AMD64 UN * X ABI selalu persis seperti itu - bagian khusus UNIX . Dokumen, x86-64.org/documentation/abi.pdf , berjudul System V Application Binary Interface, AMD64 Architecture Processor Supplement karena suatu alasan. ABI UNIX (umum) (kumpulan multi-volume, sco.com/developers/devspecs ) meninggalkan bagian untuk bab 3 khusus prosesor - Suplemen - yang merupakan konvensi pemanggilan fungsi dan aturan tata letak data untuk prosesor tertentu.
FrankH.
7
@Somejan: Microsoft Windows tidak pernah mencoba untuk menjadi dekat dengan UN * X, dan dalam hal porting Windows ke x64 / AMD64 mereka hanya memilih untuk memperluas konvensi panggilan mereka sendiri __fastcall . Anda mengklaim Win32 / Win64 tidak kompatibel, tapi kemudian, melihat dari dekat: Untuk fungsi yang mengambil dua 32bit args dan kembali 32bit, Win64 dan Win32 __fastcallsebenarnya adalah 100% kompatibel (regs sama untuk melewati dua 32bit args, yang sama nilai kembali). Bahkan beberapa kode biner (!) Dapat bekerja di kedua mode operasi. Sisi UNIX benar-benar putus dengan "cara lama". Untuk alasan yang bagus, tapi istirahat adalah istirahat.
FrankH.
2
@Olof: Ini lebih dari sekedar kompiler. Saya memiliki masalah dengan ESI dan EDI ketika saya melakukan hal-hal mandiri di NASM. Windows pasti peduli dengan register tersebut. Tetapi ya, Anda dapat menggunakannya jika Anda menyimpannya sebelum Anda melakukannya dan memulihkannya sebelum Windows membutuhkannya.
cHao