X64'te dört bağımsız değişken kaydı seçme - UN * X / Win64 için ortak
X86 hakkında akılda tutulması gereken şeylerden biri, "kayıt numarası" kodlamasının yazmaç adının açık olmamasıdır; talimat kodlaması açısından ( MOD R / M baytı, bkz. http://www.c-jump.com/CIS77/CPU/x86/X77_0060_mod_reg_r_m_byte.htm ), kayıt numaraları 0 ... 7 - bu sırayla - ?AX
, ?CX
, ?DX
, ?BX
, ?SP
, ?BP
, ?SI
, ?DI
.
Dolayısıyla, dönüş değeri için A / C / D'yi (regs 0..2) ve ilk iki argümanı ("klasik" 32 bitlik kuraldır) seçmek __fastcall
mantıklı bir seçimdir. 64bit'e gitme söz konusu olduğunda, "daha yüksek" kayıtlar sipariş edilir ve hem Microsoft hem de UN * X / Linux ilk olanlar için R8
/ R9
olarak gitti .
Bunu göz önüne aldığımızda tutulması, Microsoft'un seçimi RAX
(dönüş değeri) ve RCX
, RDX
, R8
, R9
(arg [0..3]) seçerseniz anlaşılabilir bir seçim vardır dört argümanlar için kayıtlar.
AMD64 UN * X ABI'nin neden daha RDX
önce seçtiğini bilmiyorum RCX
.
X64'te altı bağımsız değişken kaydı seçme - UN * X'e özgü
RISC mimarilerinde UN * X, geleneksel olarak kayıtlarda geçen argümanları - özellikle ilk altı argüman için (en azından PPC, SPARC, MIPS'de böyledir) yapmıştır. AMD64 (UN * X) ABI tasarımcılarının bu mimaride de altı kayıt kullanmayı seçmelerinin ana nedenlerinden biri bu olabilir.
Yani isterseniz altı bağımsız değişkenleri geçmesine kayıtları ve seçim için mantıklı RCX
, RDX
, R8
ve R9
dördü için iki başka hangi almalı?
"Daha yüksek" regler, onları seçmek için ek bir talimat ön ek baytı gerektirir ve bu nedenle daha büyük bir komut boyutu ayak izine sahiptir, bu nedenle seçenekleriniz varsa bunlardan herhangi birini seçmek istemezsiniz. Klasik kayıtlardan, örtük anlamı nedeniyle RBP
ve RSP
bunlar mevcut değildir ve RBX
geleneksel olarak, AMD64 ABI tasarımcılarının gereksiz yere uyumsuz olmak istemediği UN * X (global ofset tablosu) üzerinde özel bir kullanımı vardır.
Ergo, tek seçenek vardı RSI
/ RDI
.
Öyleyse , argüman yazmaçlarını RSI
/ RDI
olarak almanız gerekiyorsa, bunlar hangi argümanlar olmalıdır?
Bunları yapmak arg[0]
ve arg[1]
bazı avantajları vardır. CHao'nun yorumuna bakın.
?SI
ve ?DI
dize talimatı kaynağı / hedef işlenenleridir ve cHao'nun da bahsettiği gibi, argüman kayıtları olarak kullanımları, AMD64 UN * X arama kurallarıyla mümkün olan en basit strcpy()
işlevin yalnızca iki CPU talimatından oluştuğu anlamına gelir, repz movsb; ret
çünkü kaynak / hedef adresler arayan tarafından doğru kayıtlara yerleştirilmiştir. Özellikle düşük seviyeli ve derleyici tarafından üretilen "yapıştırıcı" kodunda (örneğin, bazı C ++ yığın ayırıcılarının yapım sırasında sıfır dolduran nesneleri veya çekirdeğin sıfır dolduran yığın sayfalarını düşünün.sbrk()
veya yazma üzerine kopyalama sayfa hataları) muazzam miktarda blok kopyalama / doldurma, bu nedenle bu tür kaynak / hedef adres bağımsız değişkenlerini "doğru" kayıtlar.
Yani bir bakıma, BM * X ve Win64 BM * X "prepends" iki ek argümanlar, kasten seçilmiş içinde sadece farklıdır RSI
/ RDI
kayıtları, dört bağımsız değişken doğal seçim RCX
, RDX
, R8
ve R9
.
Onun ötesinde ...
UN * X ve Windows x64 ABI'leri arasında, argümanların belirli kayıtlara eşlenmesinden daha fazla fark vardır. Win64'e genel bakış için, kontrol edin:
http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx
Win64 ve AMD64 UN * X, yığın alanının kullanım şekli açısından da çarpıcı biçimde farklılık gösterir; Win64 üzerinde, örneğin, arayan gerekir hatta args 0 ... 3 kayıtlarında geçirilen rağmen fonksiyon argümanlar için stackspace tahsis. Öte yandan, UN * X'te, bir yaprak işlevinin (yani, diğer işlevleri çağırmayan), 128 Bayttan fazlasına ihtiyaç duymuyorsa yığın alanı ayırması bile gerekmez (evet, sahipsiniz ve kullanabilirsiniz belirli miktarda yığın ayırmadan ... pekala, çekirdek kodu değilseniz, şık hataların kaynağı). Tüm bunlar belirli optimizasyon seçimleridir, bunların çoğu için mantık, orijinal posterin wikipedia referansının işaret ettiği tam ABI referanslarında açıklanmıştır.