Aracılığıyla paylaş


ARM32 ABI Kurallarına Genel Bakış

ARM işlemcilerde Windows için derlenen kod için uygulama ikili arabirimi (ABI), standart ARM EABI'yi temel alır. Bu makalede ARM üzerinde Windows ile standart arasındaki önemli farklar vurgulanır. Bu belge ARM32 ABI'yi kapsar. ARM64 ABI hakkında bilgi için bkz . ARM64 ABI kurallarına genel bakış. Standart ARM EABI hakkında daha fazla bilgi için bkz . ARM Mimarisi (dış bağlantı) için Uygulama İkili Arabirimi (ABI).

Temel Gereksinimler

ARM'de Windows her zaman bir ARMv7 mimarisinde çalıştığını varsar. VFPv3-D32 veya üzeri biçiminde kayan nokta desteği donanımda mevcut olmalıdır. VFP, donanımda hem tek duyarlıklı hem de çift duyarlıklı kayan noktayı desteklemelidir. Windows çalışma zamanı, VFP olmayan donanımlarda çalıştırmayı etkinleştirmek için kayan nokta öykünmesini desteklemez.

Hem tamsayı hem de kayan nokta işlemleri de dahil olmak üzere gelişmiş SIMD Uzantıları (NEON) desteği de donanımda bulunmalıdır. Öykünme için çalışma zamanı desteği sağlanmaz.

Tamsayı bölme desteği (UDIV/SDIV) önerilir ancak gerekli değildir. Tamsayı bölme desteği olmayan platformlar, bu işlemlerin tuzağa düşürülmesi ve büyük olasılıkla düzeltme eki uygulanmış olması gerektiğinden performans cezasına neden olabilir.

Endianness

ARM'deki Windows küçük endian modunda yürütülür. Hem MSVC derleyicisi hem de Windows çalışma zamanı her zaman küçük endian verileri bekler. ARM yönerge kümesi mimarisindeki (ISA) SETEND yönergesi, kullanıcı modu kodunun bile geçerli son hali değiştirmesine olanak tanır. Ancak, uygulama için tehlikeli olduğundan bunu yapmak önerilmez. Büyük endian modunda bir özel durum oluşturulursa, davranış tahmin edilemez. Kullanıcı modunda bir uygulama hatasına veya çekirdek modunda hata denetimine yol açabilir.

Hizalama

Windows, ARM donanımının yanlış hizalanmış tamsayı erişimlerini saydam bir şekilde işlemesini sağlar, ancak bazı durumlarda hizalama hataları yine de oluşturulabilir. Hizalama için şu kuralları izleyin:

  • Yarım sözcük boyutlu (16 bit) ve sözcük boyutlu (32 bit) tamsayı yüklerini ve depolarını hizalamanız gerekmez. Donanım bunları verimli ve şeffaf bir şekilde işler.

  • Kayan nokta yükleri ve depoları hizalanmalıdır. Çekirdek, hizalanmamış yükleri işler ve saydam olarak depolar, ancak önemli ek yükleri vardır.

  • Çift yükleme veya depolama (LDRD/STRD) ve birden çok (LDM/STM) işlemi hizalanmalıdır. Çekirdek bunların çoğunu saydam olarak işler, ancak önemli ek yükleri vardır.

  • Tamsayı erişimleri için bile tüm kazınmamış bellek erişimleri hizalanmalıdır. Hizalanmamış erişimler hizalama hatasına neden olur.

Yönerge Kümesi

ARM üzerinde Windows için ayarlanan yönerge kesinlikle Thumb-2 ile sınırlıdır. Bu platformda yürütülen tüm kodun başlatılması ve her zaman Başparmak modunda kalması beklenir. Eski ARM yönerge kümesine geçiş denemesi başarılı olabilir. Ancak bu durumda, oluşan özel durumlar veya kesintiler kullanıcı modunda bir uygulama hatasına veya çekirdek modunda bir hata denetimine neden olabilir.

Bu gereksinimin bir yan etkisi, tüm kod işaretçilerinin düşük bit kümesine sahip olması gerekir. Ardından, BLX veya BX aracılığıyla yüklenip dallandığında işlemci Başparmak modunda kalır. Hedef kodu 32 bit ARM yönergeleri olarak yürütmeye çalışmaz.

SDIV/UDIV yönergeleri

SDIV ve UDIV tamsayı bölme yönergelerinin kullanımı, bunları işlemek için yerel donanım içermeyen platformlarda bile tam olarak desteklenir. Cortex-A9 işlemcide SDIV veya UDIV bölme başına ek yük yaklaşık 80 döngüdür. Bu, girişlere bağlı olarak 20-250 döngünün genel bölme süresine eklenir.

Tamsayı yazmaçları

ARM işlemcisi 16 tamsayı yazmaçlarını destekler:

Kaydol Uçucu? Rol
r0 Uçucu Parametre, sonuç, karalama yazmaç 1
r1 Uçucu Parametre, sonuç, karalama yazmaç 2
R2 Uçucu Parametre, karalama yazmaç 3
r3 Uçucu Parametre, karalama yazmaç 4
R4 Geçici olmayan
r5 Geçici olmayan
r6 Geçici olmayan
r7 Geçici olmayan
R8 Geçici olmayan
r9 Geçici olmayan
r10 Geçici olmayan
r11 Geçici olmayan Çerçeve işaretçisi
r12 Uçucu Yordam içi-çağrı karalama yazmaç
r13 (SP) Geçici olmayan Yığın işaretçisi
r14 (LR) Geçici olmayan Bağlantı yazmaç
r15 (BILGISAYAR) Geçici olmayan Program sayacı

parametresini kullanma ve değer yazmaçları döndürme hakkında ayrıntılı bilgi için bu makaledeki Parametre Geçirme bölümüne bakın.

Windows, yığın çerçevesinin hızlı yürümesi için r11 kullanır. Daha fazla bilgi için Stack Walking bölümüne bakın. Bu gereksinim nedeniyle, r11 her zaman zincirdeki en üstteki bağlantıya işaret etmelidir. Kodunuz analiz sırasında doğru yığın yürüyüşleri oluşturmayacağından r11'i genel amaçlarla kullanmayın.

VFP yazmaçları

Windows yalnızca VFPv3-D32 yardımcı işlemci desteğine sahip ARM değişkenlerini destekler. Bu, kayan nokta yazmaçlarının her zaman mevcut olduğu ve parametre geçişi için kullanılabilmesi anlamına gelir. Ayrıca 32 yazmaç kümesinin tamamı kullanılabilir. VFP kayıtları ve kullanımları şu tabloda özetlenir:

Single Double değerleri Dörtlü Uçucu? Rol
s0-s3 d0-d1 q0 Uçucu Parametreler, sonuç, karalama yazmaç
s4-s7 d2-d3 Q1 Uçucu Parametreler, karalama yazmaç
s8-s11 d4-d5 q2 Uçucu Parametreler, karalama yazmaç
s12-s15 d6-d7 q3 Uçucu Parametreler, karalama yazmaç
s16-s19 d8-d9 q4 Geçici olmayan
s20-s23 d10-d11 q5 Geçici olmayan
s24-s27 d12-d13 q6 Geçici olmayan
s28-s31 d14-d15 q7 Geçici olmayan
d16-d31 q8-q15 Uçucu

Sonraki tabloda kayan nokta durumu ve denetim yazmaç (FPSCR) bit alanları gösterilmektedir:

Bits Anlamı Uçucu? Rol
31-28 NZCV Uçucu Durum bayrakları
27 QC Uçucu Kümülatif doygunluk
26 AHP Geçici olmayan Alternatif yarı duyarlık denetimi
25 DN Geçici olmayan Varsayılan NaN modu denetimi
24 FZ Geçici olmayan Sıfıra boşaltma modu denetimi
23-22 RMode Geçici olmayan Yuvarlama modu denetimi
21-20 Adım Geçici olmayan Vektör Stride, her zaman 0 olmalıdır
18-16 Len Geçici olmayan Vektör Uzunluğu, her zaman 0 olmalıdır
15, 12-8 IDE, IXE vb. Geçici olmayan Özel durum yakalama etkinleştirme bitleri, her zaman 0 olmalıdır
7, 4-0 IDC, IXC vb. Uçucu Toplu özel durum bayrakları

Kayan nokta özel durumları

ÇOĞU ARM donanımı IEEE kayan nokta özel durumlarını desteklemez. Donanım kayan nokta özel durumları olan işlemci değişkenlerinde, Windows çekirdeği özel durumları sessizce yakalar ve FPSCR kaydında bunları örtük olarak devre dışı bırakır. Bu eylem, işlemci varyantları arasında normalleştirilmiş davranış sağlar. Aksi takdirde, özel durum desteği olmayan bir platformda geliştirilen kod, özel durum desteği olan bir platformda çalışırken beklenmeyen özel durumlar alabilir.

Parametre geçirme

ARM ABI'de Windows, variadic olmayan işlevler için parametre geçirme için ARM kurallarını izler. ABI kuralları VFP ve Gelişmiş SIMD uzantılarını içerir. Bu kurallar , VFP uzantılarıyla birlikte ARM Mimarisi için Yordam Çağrısı Standardı'nı izler. Varsayılan olarak, ilk dört tamsayı bağımsız değişkeni ve en fazla sekiz kayan nokta veya vektör bağımsız değişkeni yazmaçlara geçirilir. Yığında daha fazla bağımsız değişken geçirilir. Bağımsız değişkenler, şu yordam kullanılarak yazmaçlara veya yığına atanır:

Aşama A: Başlatma

Başlatma, bağımsız değişken işleme başlamadan önce tam olarak bir kez gerçekleştirilir:

  1. Sonraki Çekirdek Kayıt Numarası (NCRN) r0 olarak ayarlanır.

  2. VFP yazmaçları ayrılmamış olarak işaretlenir.

  3. Sonraki Yığılmış Bağımsız Değişken Adresi (NSAA) geçerli SP'ye ayarlanır.

  4. Bellekte sonuç döndüren bir işlev çağrılırsa, sonucun adresi r0'a yerleştirilir ve NCRN r1 olarak ayarlanır.

Aşama B: Bağımsız değişkenlerin ön doldurması ve uzantısı

Listedeki her bağımsız değişken için aşağıdaki listeden ilk eşleşen kural uygulanır:

  1. Bağımsız değişken, boyutu hem çağıran hem de çağıran tarafından statik olarak belirlenemeyen bileşik bir türse, bağımsız değişken belleğe kopyalanır ve kopyanın işaretçisiyle değiştirilir.

  2. Bağımsız değişken bir bayt veya 16 bit yarım sözcükse, sıfır genişletilmiş veya 32 bit tam bir sözcükle işaret genişletilmiştir ve 4 baytlık bağımsız değişken olarak değerlendirilir.

  3. Bağımsız değişken bileşik bir türse, boyutu 4'ün en yakın katına yuvarlanmış olur.

Aşama C: Bağımsız değişkenlerin yazmaçlara ve yığına atanma

Listedeki her bağımsız değişken için, bağımsız değişken ayrılana kadar sırayla aşağıdaki kurallar uygulanır:

  1. Bağımsız değişken bir VFP türüyse ve uygun türde art arda ayrılmamış yeterli sayıda VFP yazmaç varsa, bağımsız değişken bu tür yazmaçların en düşük numaralı dizisine ayrılır.

  2. Bağımsız değişken bir VFP türüyse, kalan tüm ayrılmamış yazmaçlar kullanılamıyor olarak işaretlenir. NSAA, bağımsız değişken türü için doğru hizalanana ve bağımsız değişken ayarlanan NSAA'daki yığına kopyalanana kadar yukarı doğru ayarlanır. Ardından NSAA, bağımsız değişkenin boyutuna göre artırılır.

  3. Bağımsız değişken 8 baytlık hizalama gerektiriyorsa, NCRN bir sonraki çift kayıt numarasına yuvarlanmış olur.

  4. Bağımsız değişkenin 32 bit sözcüklerdeki boyutu r4 eksi NCRN'den fazla değilse, bağımsız değişken NCRN'den başlayarak çekirdek yazmaçlara kopyalanır ve en az önemli bitler daha düşük numaralı yazmaçları kaplar. NCRN, kullanılan yazmaç sayısına göre artırılır.

  5. NCRN r4'ten küçükse ve NSAA SP'ye eşitse, bağımsız değişken çekirdek yazmaçlarla yığın arasında bölünür. Bağımsız değişkenin ilk bölümü, r3'e kadar ve dahil olmak üzere NCRN'den başlayarak çekirdek yazmaçlara kopyalanır. Bağımsız değişkenin geri kalanı NSAA'dan başlayarak yığına kopyalanır. NCRN r4 olarak ayarlanır ve NSAA, bağımsız değişkenin boyutuyla artırılır ve yazmaçlarda geçirilen tutar çıkarılır.

  6. Bağımsız değişken 8 bayt hizalama gerektiriyorsa, NSAA bir sonraki 8 bayt hizalı adrese yuvarlanmış olur.

  7. Bağımsız değişken NSAA'daki belleğe kopyalanır. NSAA, bağımsız değişkenin boyutuna göre artırılır.

VFP yazmaçları variadic işlevler için kullanılmaz ve 1. ve 2. Aşama kuralları yoksayılır. Bu, variadic işlevin isteğe bağlı bir {r0-r3} ile başlayıp kayıt bağımsız değişkenlerini çağıran tarafından geçirilen ek bağımsız değişkenlere ekleyebileceği ve ardından bağımsız değişken listesinin tamamına doğrudan yığından erişebileceği anlamına gelir.

Tamsayı türü değerleri r0 cinsinden döndürülür ve isteğe bağlı olarak 64 bit dönüş değerleri için r1'e genişletilir. VFP/NEON kayan nokta veya SIMD türü değerleri uygun şekilde s0, d0 veya q0 cinsinden döndürülür.

Yığın

Yığının her zaman 4 bayt hizalı kalması ve herhangi bir işlev sınırında 8 bayt hizalanmış olması gerekir. 64 bit yığın değişkenlerinde kilitlenmiş işlemlerin sık kullanımını desteklemek gerekir. ARM EABI, yığının herhangi bir genel arabirimde 8 bayt hizalandığını belirtir. Tutarlılık için ARM ABI'de Windows herhangi bir işlev sınırını genel arabirim olarak kabul eder.

Çerçeve işaretçisi kullanması gereken işlevler (örneğin, çağıran alloca veya yığın işaretçisini dinamik olarak değiştiren işlevler), işlev prologunda r11'de çerçeve işaretçisini ayarlamalı ve özete kadar değişmeden bırakmalıdır. Çerçeve işaretçisi gerektirmeyen işlevlerin, prologdaki tüm yığın güncelleştirmelerini gerçekleştirmesi ve üst yazıya kadar yığın işaretçisini değiştirmeden bırakması gerekir.

Yığında 4 KB veya daha fazlasını ayıran işlevler, son sayfadan önceki her sayfaya sırayla dokunulmasını sağlamalıdır. Bu sıra, hiçbir kodun Windows'un yığını genişletmek için kullandığı koruma sayfalarını "atlamamasını" sağlar. Genişletme işlemi genellikle yardımcı tarafından __chkstk yapılır ve toplam yığın ayırması r4'te 4'e bölünür ve r4'te bayt cinsinden son yığın ayırma miktarını döndürür.

Kırmızı bölge

Geçerli yığın işaretçisinin hemen altındaki 8 baytlık alan analiz ve dinamik düzeltme eki uygulama için ayrılmıştır. 2 yazmacı [sp, #-8] depolayan ve bunları rastgele amaçlarla geçici olarak kullanan dikkatle oluşturulan kodun eklenmesine izin verir. Windows çekirdeği, hem kullanıcı modunda hem de çekirdek modunda bir özel durum veya kesinti oluşursa bu 8 bayt'ın üzerine yazılmayacağını garanti eder.

Çekirdek yığını

Windows'ta varsayılan çekirdek modu yığını üç sayfadır (12 KB). Çekirdek modunda büyük yığın arabellekleri olan işlevler oluşturmamaya dikkat edin. Çok az yığın odasıyla bir kesinti gelebilir ve yığın paniği hata denetimine neden olabilir.

C/C++ özellikleri

Numaralandırmadaki en az bir değer 64 bit çift sözcüklü depolama gerektirmediği sürece numaralandırmalar 32 bit tamsayı türleridir. Bu durumda, numaralandırma 64 bit tamsayı türüne yükseltilir.

wchar_t , diğer platformlarla uyumluluğu korumak için ile eşdeğer unsigned shortolacak şekilde tanımlanır.

Yığınla yürüme

Windows kodu, hızlı yığın yürümeyi etkinleştirmek için çerçeve işaretçileri etkinleştirilmiş (/Oy (Çerçeve İşaretçisi Atlanmış)) ile derlenmiş. Genellikle, r11 yazmacı zincirdeki bir sonraki bağlantıya işaret eder. Bu, yığındaki önceki çerçeveye ve dönüş adresine yönelik işaretçiyi belirten bir {r11, lr} çiftidir. Kodunuzun gelişmiş profil oluşturma ve izleme için çerçeve işaretçilerini de etkinleştirmesini öneririz.

Özel durum geri alma

Özel durum işleme sırasında yığın geri sarmalama, geri alma kodlarının kullanılmasıyla etkinleştirilir. Geri sarma kodları, yürütülebilir görüntünün .xdata bölümünde depolanan bir bayt dizisidir. İşlev prologue ve epilog kodunun çalışmasını soyut bir şekilde açıklar, böylece bir işlevin prologunun etkileri çağıranın yığın çerçevesine geri sarma hazırlığında geri alınabilir.

ARM EABI, geri alma kodlarını kullanan bir özel durum geri sarma modeli belirtir. Ancak bu belirtim, işlemcinin bir işlevin prologue veya epilogunun ortasında olduğu durumları işlemesi gereken Windows'ta geri sarma için yeterli değildir. ARM özel durum verileri ve geri sarma üzerinde Windows hakkında daha fazla bilgi için bkz . ARM Özel Durum İşleme.

Oluşturulan kodun özel durum işlemeye katılabilmesi için RtlAddFunctionTable dinamik olarak oluşturulan kodun ve ilişkili işlevlere yapılan çağrılarda belirtilen dinamik işlev tabloları kullanılarak açıklanması önerilir.

Döngü sayacı

Windows çalıştıran ARM işlemcilerinin bir döngü sayacını desteklemesi gerekir, ancak sayacın doğrudan kullanılması sorunlara neden olabilir. Bu sorunları önlemek için ARM'de Windows, normalleştirilmiş bir 64 bit döngü sayacı değeri istemek için tanımsız bir işlem kodu kullanır. C veya C++'dan, uygun opcode'un yaymak için iç öğesini kullanın __rdpmccntr64 ; derlemeden yönergeyi __rdpmccntr64 kullanın. Döngü sayacının okunması Cortex-A9 üzerinde yaklaşık 60 döngü sürer.

Sayaç, saat değil gerçek bir döngü sayacıdır; bu nedenle, sayım sıklığı işlemci sıklığına göre değişir. Geçen saat saatini ölçmek istiyorsanız kullanın QueryPerformanceCounter.

Ayrıca bkz.

Genel Visual C++ ARM Geçiş Sorunları
ARM Özel Durum İşleme