X86 chaqiruv konvensiyalari - X86 calling conventions

Ushbu maqolada konventsiyalarni chaqirish dasturlashda ishlatiladi x86 me'morchilik mikroprotsessorlar.

Chaqiruv konventsiyalari chaqirilgan kodning interfeysini tavsiflaydi:

  • Atom (skalar) parametrlari yoki murakkab parametrning alohida qismlari ajratish tartibi
  • Parametrlar qanday o'tkaziladi (stekka suriladi, registrlarga joylashtiriladi yoki ikkalasining aralashmasi)
  • Qanday qilib chaqirilgan funktsiyani ro'yxatdan o'tkazuvchi qo'ng'iroq qiluvchini saqlab qo'yishi kerak (shuningdek: qo'ng'iroq qiluvchilar uchun saqlangan registrlar yoki o'zgarmas registrlar)
  • Qanday qilib stekni tayyorlash va funktsiya chaqiruvini tiklash vazifasi qo'ng'iroq qiluvchiga va suhbatdoshga bo'linadi

Bu dasturlash tillarining o'lchamlari va formatlarini belgilash bilan chambarchas bog'liq, yana bir yaqin mavzu mangling nomlari bu kod xaritasidagi belgi nomlarini bog'lovchi tomonidan ishlatiladigan belgilar nomlariga qanday belgilashini belgilaydi. Konventsiyalarni chaqirish, turdagi vakolatxonalar va ismlarni almashtirish - bu an deb nomlanuvchi narsalarning bir qismidir dastur ikkilik interfeysi (ABI).

Turli xil kompilyatorlarning ushbu konventsiyalarni amalga oshirishda ko'pincha farqlar mavjud, shuning uchun ko'pincha turli xil kompilyatorlar tomonidan tuzilgan kodni interfeys qilish qiyin. Boshqa tomondan, API standarti sifatida ishlatiladigan konventsiyalar (masalan, stdcall) juda bir xilda amalga oshiriladi.

Tarixiy ma'lumot

Gacha mikrokompyuterlar, Mashina ishlab chiqaruvchisi odatda an operatsion tizim va kompilyatorlar bir necha kishi uchun dasturlash tillari. The konvensiyani chaqirish Har bir platforma uchun ishlab chiqaruvchining dasturlash vositalari tomonidan aniqlangan platformalar.

Commodore Pet-dan oldingi mikrokompyuterlar va Apple II odatda OS yoki kompilyatorlarsiz keladi. The IBM PC Microsoft-ning oldingi versiyasi bilan Windows-ga, Disk Operatsion tizimiga (DOS ), lekin u kompilyator bilan birga kelmagan. Yagona apparat standart uchun IBM PC-ga mos keladi mashinalari Intel protsessorlari (8086, 80386) va so'zma-so'z IBM jo'natildi. Uskuna kengaytmalari va barchasi dasturiy ta'minot standartlari (a uchun saqlang BIOS chaqirish konvensiyasi) bozor raqobatiga ochiq tashlandi.

Ko'plab mustaqil dasturiy ta'minot firmalari operatsion tizimlar, ko'plab dasturlash tillari uchun kompilyatorlar va dasturlarni taklif qilishdi. Ko'p turli xil qo'ng'iroq sxemalari firmalar tomonidan ko'pincha turli xil talablar, tarixiy amaliyotlar va dasturchilarning ijodkorligi asosida bir-birini inkor etgan holda amalga oshirildi.

IBM-ga mos keladigan bozor chayqalishidan so'ng, Microsoft operatsion tizimlar va dasturlash vositalari (turli xil konvensiyalar bilan) ustunlik qildi, ikkinchi darajali firmalar esa Borland va Novell va shunga o'xshash ochiq manbali loyihalar GCC, hali ham o'z standartlarini saqlab qolishdi. Uchun qoidalar birgalikda ishlash oxir-oqibat sotuvchilar va mahsulotlar o'rtasida qabul qilinib, hayotiy konvensiyani tanlash muammosi soddalashtirildi.[1]

Qo'ng'iroqni tozalash

Ushbu konventsiyalarda qo'ng'iroq qiluvchi argumentlarni stekdan tozalaydi.

cdecl

The cdecl (bu degani) C deklaratsiyasi) Microsoft-ning kompilyatoridan kelib chiqqan chaqiruv konvensiyasidir C dasturlash tili va ko'plab C kompilyatorlari tomonidan x86 arxitekturasi.[1] Cdecl-da subroutine argumentlari suyakka. Butun sonlar va xotira manzillari EAX-da qaytariladi ro'yxatdan o'tish, ST0 da suzuvchi nuqta qiymatlari x87 ro'yxatdan o'tish. EAX, ECX va EDX registrlari qo'ng'iroq qiluvchidan, qolganlari esa qo'ng'iroq qiluvchidan saqlanadi. The x87 ST0 dan ST7 gacha suzuvchi nuqta registrlari yangi funktsiyani chaqirishda bo'sh bo'lishi kerak (qo'yilgan yoki bo'shatilgan), funktsiyadan chiqishda ST1 dan ST7 gacha bo'sh bo'lishi kerak. ST0 qiymat qaytarish uchun ishlatilmaganda ham bo'sh bo'lishi kerak.

C dasturlash tili kontekstida funktsiya argumentlari stakka o'ngdan chapga tartibda suriladi, ya'ni oxirgi argument birinchi bo'lib suriladi.

Quyidagi C manba kodini ko'rib chiqing:

int kalli(int, int, int);int chaqiruvchi(bekor){	qaytish kalli(1, 2, 3) + 5;}

Yoqilgan x86, u quyidagilarni keltirib chiqarishi mumkin yig'ilish kodi (Intel sintaksisi ):

qo'ng'iroq qiluvchi:    ; yangi qo'ng'iroq doirasini yaratish    ; (ba'zi kompilyatorlar buning o'rniga "enter" buyrug'ini ishlab chiqishi mumkin)    Durang    ebp       ; eski qo'ng'iroq doirasini saqlash    mov     ebp, esp  ; yangi qo'ng'iroq doirasini ishga tushirish    ; teskari tomonga qo'ng'iroq argumentlarini bosing    ; (ba'zi kompilyatorlar stack ko'rsatkichidan kerakli joyni olib tashlashi mumkin,    ; keyin har bir dalilni to'g'ridan-to'g'ri yozing, pastga qarang.    ; "Enter" ko'rsatmasi ham shunga o'xshash narsalarni qilishi mumkin)    ; sub esp, 12: "enter" ko'rsatmasi biz uchun buni amalga oshirishi mumkin    ; mov [ebp-4], 3: yoki mov [esp + 8], 3    ; mov [ebp-8], 2: yoki mov [esp + 4], 2    ; mov [ebp-12], 1: yoki mov [esp], 1    Durang    3    Durang    2    Durang    1    qo'ng'iroq qiling    kalli    ; subroutine-ni "chaqiruvchi" deb nomlash    qo'shish     esp, 12   ; qo'ng'iroq argumentlarini freymdan olib tashlash    qo'shish     eax, 5    ; subroutine natijasini o'zgartirish                      ; (eax - bu bizning suhbatdoshimizning qaytish qiymati,                      ; shuning uchun uni mahalliy o'zgaruvchiga ko'chirishimiz shart emas)    ; eski qo'ng'iroq doirasini tiklash    ; (ba'zi kompilyatorlar buning o'rniga "ta'til" ko'rsatmasini berishi mumkin)    mov     esp, ebp  ; aksariyat chaqiriq konventsiyalari ebp-ni chaqiruvchilar tomonidan saqlanishini talab qiladi,                      ; ya'ni chaqiruvchini chaqirgandan keyin saqlanib qoladi.                      ; shuning uchun u hali ham bizning stek ramkamizning boshlanishiga ishora qiladi.                      ; ishonch hosil qilishimiz kerak                      ; Callee ebp-ni o'zgartirmaydi (yoki tiklamaydi), ammo                      ; shuning uchun biz ishonch hosil qilishimiz kerak                      ; u buni amalga oshiradigan chaqiruv konventsiyasidan foydalanadi    pop     ebp       ; eski qo'ng'iroq doirasini tiklash    ret               ; qaytish

Qo'ng'iroq qiluvchi funktsiya chaqiruvi qaytib kelgandan keyin stekni tozalaydi.

The cdecl chaqiruv konvensiyasi odatda x86 C uchun standart chaqiruv konvensiyasi hisoblanadi kompilyatorlar, garchi ko'plab kompilyatorlar ishlatilgan chaqiruv konventsiyalarini avtomatik ravishda o'zgartirish imkoniyatini beradi. Cdecl funktsiyasini qo'lda belgilash uchun ba'zilari quyidagi sintaksisni qo'llab-quvvatlaydi:

return_type __cdecl funktsiya nomi();

O'zgarishlar

Cdecl talqinida ba'zi farqlar mavjud. Natijada, turli xil operatsion tizim platformalari va / yoki turli xil kompilyatorlar tomonidan tuzilgan x86 dasturlari, hatto ikkalasi ham "cdecl" konventsiyasidan foydalansa ham, asosiy muhitni chaqirmasa ham, mos kelmasligi mumkin.

Qanday qilib qiymatlarni qaytarish borasida ba'zi kompilyatorlar registrlar juftligi EAX: EDX da uzunligi 2 registrdan kam bo'lgan oddiy ma'lumotlar tuzilmalarini va istisno ishlovchisi tomonidan maxsus ishlov berishni talab qiladigan kattaroq tuzilmalar va sinf ob'ektlarini qaytaradilar (masalan, belgilangan konstruktor, destruktor yoki tayinlash) xotiraga qaytariladi. "Xotirada" o'tish uchun qo'ng'iroq qiluvchi xotirani ajratadi va unga ko'rsatgichni yashirin birinchi parametr sifatida uzatadi; chaqiruvchi xotirani to'ldiradi va ko'rsatgichni qaytaradi, qaytib kelganda yashirin ko'rsatgichni chiqaradi.[2]

Yilda Linux, GCC belgilaydi amalda konventsiyalarni chaqirish uchun standart. GCC 4.5 versiyasidan beri funktsiyani chaqirishda stek 16 baytli chegaraga to'g'ri kelishi kerak (oldingi versiyalarda faqat 4 baytli tekislash kerak edi).[1][3]

Ning versiyasi cdecl i386 tizimlari uchun V ABI tizimida tasvirlangan.[4]

syscall

Bu cdecl-ga o'xshaydi, chunki argumentlar o'ngdan chapga suriladi. EAX, ECX va EDX saqlanmagan. Ikki so'zli parametrlar ro'yxati hajmi AL-ga uzatiladi.

Syscall - bu 32 bitli standart qo'ng'iroq konvensiyasi OS / 2 API.

optlink

Argumentlar o'ngdan chapga suriladi. Uchta birinchi (eng chap) argumentlar EAX, EDX va ECX da, to'rttagacha suzuvchi nuqta ST0 da ST3 orqali uzatiladi, ammo ular uchun joy stackdagi argumentlar ro'yxatida saqlanadi. Natijalar EAX yoki ST0 da qaytariladi. EBP, EBX, ESI va EDI registrlari saqlanib qolgan.

Optlink tomonidan ishlatiladi IBM VisualAge kompilyatorlar.

Callee tozalash

Ushbu konventsiyalarda kallel argumentlarni stakdan tozalaydi. Ushbu konventsiyalardan foydalanadigan funktsiyalarni ASM kodida tanib olish oson, chunki ular qaytib kelganidan keyin to'plamni echishadi. X86 ret ko'rsatma, qo'ng'iroq qiluvchiga qaytib kelganidan keyin bo'shatiladigan baytlar sonini belgilaydigan ixtiyoriy 16-bitli parametrga imkon beradi. Bunday kod quyidagicha ko'rinadi:

ret 12

Konventsiyalar tezkor qo'ng'iroq yoki ro'yxatdan o'tish standartlashtirilmagan va kompilyator sotuvchisiga qarab turlicha amalga oshirilgan.[1] Odatda ro'yxatdan o'tishga asoslangan qo'ng'iroqlar konventsiyalari registrlarda bir yoki bir nechta argumentlarni uzatadi, bu esa qo'ng'iroq uchun zarur bo'lgan xotiraga kirishni kamaytiradi va shu bilan ularni tezroq bajaradi.

paskal

Asosida Borland Paskal dasturlash tilining chaqiruv konvensiyasi, parametrlar stekka chapdan o'ngga (cdecl-ga qarama-qarshi) tartibda suriladi va qo'ng'iroq qiluvchi ularni stakdan olib tashlash uchun javobgardir.

Natijani qaytarish quyidagicha ishlaydi:

  • Oddiy qiymatlar AL (8 bitli qiymatlar), AX (16 bitli qiymatlar), EAX (32 bitli qiymatlar) yoki DX: AX (16 bitli tizimlarda 32 bitli qiymatlar) shaklida qaytariladi.
  • Haqiqiy qiymatlar DX: BX: AX-da qaytariladi.
  • Suzuvchi nuqta (8087) qiymatlari ST0 ga qaytariladi.
  • Ko'rsatkichlar EAX-da 32-bitli tizimlarda va AX-da 16-bitli tizimlarda qaytariladi.
  • Satrlar @Result belgisi tomonidan ko'rsatilgan vaqtinchalik joyda qaytariladi.

Ushbu chaqiruv konventsiyasi quyidagi 16-bitli API-larda keng tarqalgan edi: OS / 2 1.x, Microsoft Windows 3.x va Borland Delphi 1.x versiyasi Windows API-ning zamonaviy versiyalari stdcall, Paskal konvensiyasida bo'lgani kabi, hanuzgacha kalle stekni tiklaydi, ammo parametrlar endi o'ngga chapga suriladi.

stdcall

Stdcall[5] chaqiruv konvensiyasi - Paskal tilidagi chaqiruv konvensiyasidagi o'zgarish, bu da'vogar stekni tozalash uchun javobgardir, lekin parametrlar stek ustiga o'ng tomonga chapga suriladi, masalan, _cdecl chaqirish konvensiyasida. EAX, ECX va EDX registrlari funktsiya doirasida foydalanish uchun mo'ljallangan. Qaytish qiymatlari EAX registrida saqlanadi.

stdcall - bu Microsoft uchun standart qo'ng'iroq konvensiyasi Win32 API va uchun Watcom C ++ dasturini oching.

Microsoft tezkor chaqiruvi

Microsoft __fastcall anjuman (aka __msfastcall) ECX va EDX ga mos keladigan dastlabki ikkita argumentni (chapdan o'ngga baholanadi) o'tkazadi.[6] Qolgan argumentlar stakka o'ngdan chapga suriladi. Qachon kompilyator kompilyatsiya qiladi IA64 yoki AMD64, bu e'tibor bermaydi __fastcall kalit so'z va foydalanish bitta 64-bitli qo'ng'iroq konvensiyasi o'rniga.

Juda keng tarqalgan chaqiruv konvensiyasi sifatida GCC, Clang va ICC kabi boshqa kompilyatorlar ham tezkor qo'ng'iroqni qo'llab-quvvatlaydi.[7]

Microsoft vectorcall

Visual Studio 2013-da Microsoft __vectorcall o'yin, grafik, video / audio va kodek ishlab chiqaruvchilarning samaradorligi bilan bog'liq muammolarga javoban konvensiyani chaqirish. Sxema katta vektor turlariga imkon beradi (suzmoq, ikki baravar, __m128, __m256) stackdan farqli o'laroq registrlarga o'tkazilishi kerak.[8]

IA-32 va x64 kodlari uchun __vectorcall ga o'xshash __fastcall va asl x64 konventsiyalarni mos ravishda chaqirish, lekin ularni vektorli argumentlarni ishlatishda qo'llab-quvvatlash uchun kengaytiradi SIMD registrlar. IA-32 da tamsayı qiymatlari odatdagidek o'tkaziladi va birinchi oltita SIMD (XMM /YMM 0-5) registrlar oltita suzuvchi nuqta, vektor yoki HVA qiymatlarini ketma-ket chapdan o'ngga, masalan, sabab bo'lgan haqiqiy pozitsiyalarga qaramasdan ushlab turadilar. ular o'rtasida paydo bo'ladigan int argument. X64-da, x64-ning asl konventsiyasidagi qoida hali ham amal qiladi, shuning uchun XMM / YMM0-5 faqat suzuvchi nuqta, vektor yoki HVA argumentlarini oltinchi marta birinchi bo'lib sodir bo'lganda saqlaydi.[9]

__vectorcall bir xil vektor yig'indisi (HVA) qiymatlarini uzatishni qo'llab-quvvatlaydi, ular bir xil oltita registrdan foydalangan holda faqat to'rtta bir xil vektor turlaridan tashkil topgan kompozit turlar (tuzilmalar). Vektorli turdagi argumentlar uchun registrlar ajratilgandan so'ng, foydalanilmagan registrlar HVA argumentlariga chapdan o'ngga taqsimlanadi. Joylashuv qoidalari hali ham amal qiladi. Olingan vektor turi va HVA qiymatlari dastlabki to'rtta XMM / YMM registri yordamida qaytariladi.[9]

Clang kompilyatori va Intel C ++ kompilyatori vektor chaqirishni ham amalga oshiradi.[10] Intel C ++ kompilyatori shunga o'xshash, avvalgi konventsiyaga ega edi __regat; uni jarang bilan ham qo'llab-quvvatlaydi.[11]

Borland registri

Argumentlarni chapdan o'ngga baholab, uchta argumentni EAX, EDX, ECX orqali uzatadi. Qolgan argumentlar stakka, shuningdek chapdan o'ngga suriladi.[12] Bu 32-bitli kompilyatorning standart chaqiruv konvensiyasi Delphi, qaerda u sifatida tanilgan ro'yxatdan o'tish. Ushbu chaqiruv konvensiyasi Embarcadero-ning C ++ Builder tomonidan ham qo'llaniladi, u erda u chaqiriladi __fastcall.[13] Ushbu kompilyatorda Microsoft-ning tezkor qo'ng'iroq sifatida ishlatilishi mumkin __msfastcall.[14]

Shunga o'xshash qo'ng'iroq konventsiyasidan foydalanish uchun GCC va Clang-dan foydalanish mumkin __stdcall bilan regparm funktsiya atributi yoki -mregparm = 3 almashtirish. (Yig'ma tartibi teskari.) Shuningdek, qo'ng'iroqni tozalash variantini ishlab chiqarish mumkin cdecl yoki SSE registrlaridan foydalanish uchun kengaytiring.[15] A cdeclasoslangan versiya Linux yadrosi tomonidan i386 da 2.6.20 (2007 yil fevralda chiqarilgan) versiyasidan beri foydalaniladi.[16]

Watcom registri

Watcom qo'llab-quvvatlamaydi __fastcall taxallusdan tashqari kalit so'z, uni bekor qilish. Ro'yxatdan o'tish chaqiruvi konvensiyasi buyruq qatorini almashtirish orqali tanlanishi mumkin. (Ammo, IDA foydalanadi __fastcall baribir bir xillik uchun.)

EAX, EDX, EBX, ECX tartibidagi argumentlarga 4 tagacha registrlar beriladi. Argumentlar registrlarga chapdan o'ngga beriladi. Agar biron bir argumentni registrga berib bo'lmaydigan bo'lsa (u juda katta bo'lsa), u va undan keyingi barcha argumentlar to'plamga tayinlanadi. Stekka berilgan argumentlar o'ngdan chapga suriladi. Ismlar qo'shimchali pastki chiziq qo'shib manglay qilinadi.

Variadic funktsiyalari Watcom stack-ga asoslangan chaqiruv konvensiyasiga qaytadi.

Watcom C / C ++ kompilyatori ham #pragma aux[17] foydalanuvchi o'z chaqiruv konventsiyasini belgilashga imkon beradigan ko'rsatma. Uning qo'llanmasida aytilganidek: "Ushbu usul juda kam foydalanuvchilarga kerak bo'lishi mumkin, ammo agar kerak bo'lsa, u qutqaruvchi bo'lishi mumkin".

TopSpeed ​​/ Clarion / JPI

Dastlabki to'rtta parametr eax, ebx, ecx va edx registrlarida uzatiladi. Suzuvchi nuqta parametrlari suzuvchi nuqta stekiga uzatiladi - st0, st1, st2, st3, st4, st5 va st6 registrlari. Strukturaning parametrlari har doim stakka uzatiladi. Qo'shimcha parametrlar registrlar tugagandan so'ng stekka uzatiladi. Butun son qiymatlari eax, ko'rsatgichlar edx va suzuvchi nuqta turlari st0 ga qaytariladi.

xavfsiz qo'ng'iroq

Yilda Delphi va Bepul Paskal kuni Microsoft Windows, xavfsiz qo'ng'iroq konvensiyasi COM-ni o'z ichiga oladi (Komponent ob'ekti modeli ) xatolar bilan ishlash, shuning uchun istisnolar qo'ng'iroq qiluvchiga etkazilmaydi, lekin bu haqda xabar beradi HREZULT MAQOMOTI / OLE talabiga binoan qaytib keladigan qiymat. Delphi kodidan xavfsiz qo'ng'iroq funktsiyasini chaqirganda, Delphi avtomatik ravishda qaytarilgan HRESULT-ni tekshiradi va agar kerak bo'lsa, istisno tug'diradi.

Safecall chaqiruv konvensiyasi stdcall chaqiruv konvensiyasi bilan bir xil, faqat istisnolar EAX-da qo'ng'iroq qiluvchiga HResult sifatida qaytariladi (FS o'rniga: [0] o'rniga), funktsiya natijasi stekka havola orqali uzatiladi garchi bu yakuniy "chiqish" parametri bo'lsa ham. Delphi-dan Delphi funktsiyasini chaqirganda, ushbu chaqiruv konvensiyasi boshqa har qanday qo'ng'iroq konvensiyasi singari paydo bo'ladi, chunki istisnolar EAX-da qaytarilgan bo'lsa ham, ular avtomatik ravishda qo'ng'iroq qiluvchi tomonidan tegishli istisnolarga aylantiriladi. Boshqa tillarda yaratilgan MAQOMOTI ob'ektlaridan foydalanganda HResultlar avtomatik ravishda istisno tariqasida ko'tariladi va Get funktsiyalari natijasi parametr o'rniga natijada bo'ladi. Xavfsiz qo'ng'iroq bilan Delphi-da MAQOMOTI ob'ektlarini yaratishda HResultlardan xavotirlanishga hojat yo'q, chunki istisnolar odatdagidek ko'tarilishi mumkin, ammo boshqa tillarda HResult sifatida ko'riladi.

funktsiya function_name(a: DWORD): DWORD; xavfsiz qo'ng'iroq;

Natijani qaytaradi va oddiy Delphi funktsiyasi kabi istisnolarni keltirib chiqaradi, lekin u qiymatlar va istisnolarni xuddi shunday o'tkazadi:

funktsiya function_name(a: DWORD; chiqib Natija: DWORD): HRultivatsiya; stdcall;

Qo'ng'iroq qiluvchilarni yoki chaqiruvchilarni tozalash

bu chaqiriq

Ushbu chaqiruv konvensiyasi C ++ ning statik bo'lmagan a'zo funktsiyalarini chaqirish uchun ishlatiladi. Ning ikkita asosiy versiyasi mavjud bu chaqiriq kompilyatorga va funktsiya o'zgaruvchan sonli argumentlardan foydalanadimi yoki yo'qligiga qarab ishlatiladi.

GCC kompilyatori uchun bu chaqiriq deyarli bir xil cdecl: Chaqiruvchi stekni tozalaydi va parametrlar o'ngdan chapga tartibda uzatiladi. Farqning qo'shilishi bu ko'rsatgich, bu funktsiya prototipidagi birinchi parametr kabi, stekka oxirgi marta suriladi.

Microsoft Visual C ++ kompilyatorida bu ko'rsatkich ECX-da uzatiladi va u kalli oynani aks ettiruvchi stakni tozalaydi stdcall ushbu kompilyator uchun C va Windows API funktsiyalarida ishlatiladigan konventsiya. Funktsiyalar o'zgaruvchan miqdordagi argumentlardan foydalanganda, bu to'plamni tozalaydigan qo'ng'iroq qiluvchi (qarang). cdecl).

The bu chaqiriq chaqiruv konvensiyasi faqat Microsoft Visual C ++ 2005 va undan keyingi versiyalarida aniq ko'rsatilishi mumkin. Boshqa har qanday kompilyatorda bu chaqiriq kalit so'z emas. (Ammo, demontajchilar, masalan IDA, uni ko'rsatishi kerak. Shunday qilib, IDA kalit so'zdan foydalanadi nilufar Buning uchun.)

Ro'yxatdan o'tishni saqlash

Qo'ng'iroq konventsiyasining yana bir qismi - bu registrlar subroutine chaqirig'idan keyin o'z qiymatlarini saqlab qolish kafolatidir.

Qo'ng'iroqni saqlaydigan (o'zgaruvchan) registrlar

Kompilyatorlarning katta qismi mos keladigan Intel ABI-ga ko'ra, EAX, EDX va ECX protsedura yoki funktsiya doirasida foydalanish uchun bepul bo'lishi kerak va ularni saqlab qolish shart emas.[iqtibos kerak ].

Nomidan ko'rinib turibdiki, ushbu umumiy maqsadli registrlar odatda vaqtinchalik (o'zgaruvchan) ma'lumotlarga ega bo'lib, ularni har qanday pastki dastur yozishi mumkin.

Shu sababli, subroutine chaqirig'idan keyin o'z qiymatlarini tiklashni istasangiz, ushbu registrlarning har birini stakka surish uchun qo'ng'iroq qiluvchining vazifasi.

Callee tomonidan saqlanadigan (o'zgaruvchan bo'lmagan) registrlar

Boshqa registrlar qo'ng'iroqlar davomida saqlanishi kerak bo'lgan uzoq muddatli qiymatlarni (o'zgarmas) saqlash uchun ishlatiladi.

Boshqacha qilib aytganda, qo'ng'iroq qiluvchi protsedura chaqiruvini amalga oshirganda, qo'ng'iroq qiluvchining qaytib kelishidan keyin ushbu registrlar bir xil qiymatga ega bo'lishini kutishlari mumkin.

Shunday qilib, qo'ng'iroq qiluvchiga qaytib kelishdan oldin ularni saqlash (boshida surish) va tiklash (shunga ko'ra pop) uchun javobgarlikni o'z zimmasiga oladi. Oldingi holatda bo'lgani kabi, ushbu amaliyot faqat chaqiruvchi o'zgargan registrlarda amalga oshirilishi kerak.

x86-64 chaqiruv konvensiyalari

x86-64 chaqiruv konventsiyalari qo'shimcha registr maydonidan foydalanib, registrlarda ko'proq argumentlarni o'tkazadi. Shuningdek, mos kelmaydigan qo'ng'iroq konventsiyalari soni kamaytirildi. Umumiy foydalanishda ikkitasi mavjud.

Microsoft x64 chaqiruv konvensiyasi

Microsoft x64 chaqiruv konvensiyasi[18][19] ta'qib qilinadi Windows va oldindan yuklash UEFI (uchun uzoq rejim kuni x86-64 ). Dastlabki to'rt dalil registrlarga joylashtiriladi. Bu tamsayı, struct yoki ko'rsatgich argumentlari uchun RCX, RDX, R8, R9 (shu tartibda) va suzuvchi nuqta argumentlar uchun XMM0, XMM1, XMM2, XMM3 degan ma'noni anglatadi. Qo'shimcha dalillar to'plamga suriladi (o'ngdan chapga). Butun sonni qaytarish qiymatlari (x86 ga o'xshash), agar 64 bit yoki undan kam bo'lsa, RAX-da qaytariladi. Suzuvchi nuqta qaytish qiymatlari XMM0-da qaytariladi. Uzunligi 64 bitdan kam bo'lgan parametrlar nolga kengaytirilmaydi; yuqori bitlar nolga teng emas.

O'lchamlari butun songa mos keladigan tuzilmalar va birlashmalar xuddi tamsayılar singari uzatiladi va qaytariladi. Aks holda ular argument sifatida ishlatilganda ko'rsatgich bilan almashtiriladi. Katta o'lchamdagi strukturani qaytarish kerak bo'lganda, qo'ng'iroq qiluvchi tomonidan taqdim etilgan bo'shliqqa yana bir ko'rsatgich birinchi dalil sifatida o'rnatiladi va boshqa barcha argumentlarni o'ng tomonga bir joyga o'zgartiradi.[20]

Windows kontekstida x64 arxitekturasini kompilyatsiya qilishda (Microsoft yoki Microsoft-dan tashqari vositalardan foydalangan holda), stdcall, thiscall, cdecl va fastcall-ning barchasi ushbu konventsiyadan foydalanishga qaror qilishadi.

Microsoft x64 chaqiruv konvensiyasida, qo'ng'iroq qiluvchining vazifasi, funktsiyani chaqirishdan oldin (ishlatilgan parametrlarning haqiqiy sonidan qat'iy nazar) stakka 32 bayt "soya maydoni" ni ajratish va qo'ng'iroqdan keyin stekni ochishdir. Soya maydoni RCX, RDX, R8 va R9 ni to'kish uchun ishlatiladi,[21] ammo barcha funktsiyalar, hatto to'rtta parametrdan kam bo'lganlar uchun ham mavjud bo'lishi kerak.

RAX, RCX, RDX, R8, R9, R10, R11 registrlari o'zgaruvchan (qo'ng'iroq qiluvchi tomonidan saqlangan) hisoblanadi.[22]

RBX, RBP, RDI, RSI, RSP, R12, R13, R14 va R15 registrlari o'zgarmas hisoblanadi (chaqiriluvchi tomonidan saqlanadi).[22]

Masalan, 5 tamsayıli argumentlarni qabul qiladigan funktsiya registrlarda to'rtdan birini egallaydi va beshinchisi soya maydoni ustiga suriladi. Shunday qilib, chaqirilgan funktsiya kiritilganda, stek (ortib boruvchi tartibda) orqaga qaytish manzilidan, so'ngra soya bo'shligidan (32 bayt) keyin beshinchi parametrdan iborat bo'ladi.

Yilda x86-64, Visual Studio 2008 suzuvchi nuqta raqamlarini XMM6 va XMM7 da saqlaydi (shuningdek XMM8 orqali XMM15 gacha); binobarin, uchun x86-64, XMM6 va XMM7-ni (taqqoslaganda) foydalanuvchi tomonidan yozilgan yig'ilish tili dasturlari saqlashi kerak x86 bu erda foydalanuvchi tomonidan yozilgan yig'ilish tili tartib-qoidalari XMM6 va XMM7-ni saqlashga hojat yo'q edi). Boshqacha qilib aytganda, XMM6 va XMM7-ni funktsiyadan oldin / keyin saqlash / tiklash uchun foydalanuvchi tomonidan yozilgan montaj tili tartiblarini yangilash kerak. x86 ga x86-64.

Visual Studio 2013 dan boshlab, Microsoft __vectorcall x64 konventsiyasini kengaytiradigan konvensiyani chaqirish.

Tizim V AMD64 ABI

Ning chaqiruv konvensiyasi Tizim V AMD64 ABI ta'qib qilinadi Solaris, Linux, FreeBSD, macOS,[23] va Unix va Unixga o'xshash operatsion tizimlar orasida amalda standart hisoblanadi. Birinchi oltita tamsayı yoki ko'rsatgich argumentlari RDI, RSI, RDX, RCX, R8, R9 registrlarida beriladi (R10 ichki funktsiyalar holatida zanjirli ko'rsatgich sifatida ishlatiladi[24]:21), birinchi o'zgaruvchan nuqta argumentlari uchun XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6 va XMM7 ishlatiladi.[24]:22 Microsoft x64 chaqiruv konvensiyasida bo'lgani kabi, qo'shimcha argumentlar stekka uzatiladi.[24]:22 64 bitgacha bo'lgan butun sonli qaytarilish qiymatlari RAXda, 128 bitgacha bo'lgan qiymatlar RAX va RDXda saqlanadi. Suzuvchi nuqta qaytish qiymatlari xuddi shunday XMM0 va XMM1 da saqlanadi.[24]:25 Kengroq YMM va ZMM registrlari mavjud bo'lganda XMM o'rniga kengroq qiymatlarni o'tkazish va qaytarish uchun ishlatiladi.[24]:26,55

Agar qo'ng'iroq qiluvchi RBX, RSP, RBP va R12-R15 registrlaridan foydalanishni xohlasa, qo'ng'iroq qiluvchiga boshqaruvni qaytarishdan oldin u asl qiymatlarini tiklashi kerak. Qolgan barcha registrlarni, agar u o'z qadriyatlarini saqlab qolishni istasa, qo'ng'iroq qiluvchi tomonidan saqlashi kerak.[24]:16

Barg tugunlari funktsiyalari uchun (boshqa funktsiyalarni (funktsiyalarni) chaqirmaydigan funktsiyalar)) 128 baytli bo'sh joy funktsiya to'plamining ko'rsatgichi ostida saqlanadi. Bo'shliq qizil zona. Ushbu zonani biron bir signal yoki to'xtatuvchi ishlovchilar to'sib qo'ymaydi. Shunday qilib kompilyatorlar mahalliy o'zgaruvchilarni saqlash uchun ushbu zonadan foydalanishlari mumkin. Ushbu zonadan foydalanib, kompilyatorlar funktsiya boshlanishida ba'zi ko'rsatmalarni (RSP, RBP sozlamalari) o'tkazib yuborishi mumkin. Biroq, boshqa funktsiyalar ushbu zonani to'sib qo'yishi mumkin. Shuning uchun bu zonani faqat barg tugunlari funktsiyalari uchun ishlatish kerak. gcc va jarang taklif qilish -mno-qizil-zona qizil zona optimallashtirishni o'chirish uchun bayroq.

Agar chaqiruvchi a variadik funktsiya, keyin vektor registrlaridagi funktsiyaga uzatiladigan suzuvchi nuqta argumentlari soni AL registridagi chaqiruvchi tomonidan taqdim etilishi kerak.[24]:55

Microsoft-ning chaqiruv konventsiyasidan farqli o'laroq, soya maydoni ta'minlanmagan; funktsiyani kiritishda qaytish manzili stekdagi ettinchi tamsayı argumentiga qo'shni.

X86 qo'ng'iroq konvensiyalari ro'yxati

Bu x86 chaqiruv konventsiyalarining ro'yxati.[1] Bu asosan C / C ++ kompilyatorlari uchun mo'ljallangan konvensiyalar (ayniqsa quyida joylashgan 64 bitli qism) va shuning uchun asosan maxsus holatlar. Amalga oshirishda boshqa tillar boshqa format va konventsiyalardan foydalanishi mumkin.

ArxitekturaIsmOperatsion tizim, kompilyatorParametrlarYig'malarni tozalashIzohlar
Ro'yxatdan o'tish kitoblariYig'ma buyurtma
8086cdeclRTL (C)Chaqiruvchi
PaskalLTR (Paskal)Kalli
tezkor qo'ng'iroq (a'zo bo'lmagan)MicrosoftAX, DX, BXLTR (Paskal)KalliQaytish ko'rsatkichi BX-da.
fastcall (a'zo funktsiyasi)MicrosoftAX, DXLTR (Paskal)Kallibu stack past manzilida. Qaytish ko'rsatkichi AX-da.
tezkor qo'ng'iroqTurbo C[25]AX, DX, BXLTR (Paskal)Kallibu stack past manzilida. Stack yuqori manzilidagi ko'rsatkichni qaytaring.
WatcomAX, DX, BX, CXRTL (C)KalliSI-da qaytish ko'rsatkichi.
IA-32cdeclUnixga o'xshash (GCC )RTL (C)ChaqiruvchiStruct / class-ni qaytarishda chaqiruvchi kod bo'sh joy ajratadi va stakka yashiringan parametr orqali bu bo'shliqqa ko'rsatkichni uzatadi. Chaqirilgan funktsiya ushbu manzilga qaytish qiymatini yozadi.

Xato tufayli stek 16 baytli chegarada hizalanadi.

cdeclMicrosoftRTL (C)ChaqiruvchiStruct / class-ni qaytarishda,
  • Oddiy eski ma'lumotlar (POD) qaytish qiymatlari 32 bit yoki undan kichikroq EAX registrida
  • 33-64 bit hajmdagi POD qaytish qiymatlari EAX: EDX registrlari orqali qaytariladi.
  • POD-dan tashqari qiymatlar yoki 64-bitdan kattaroq qiymatlarni qaytarish, chaqiruv kodi bo'sh joy ajratadi va stakka yashirin parametr orqali ko'rsatgichni bu bo'shliqqa uzatadi. Chaqirilgan funktsiya ushbu manzilga qaytish qiymatini yozadi.

Stek 4 baytli chegarada hizalanadi.

stdcallMicrosoftRTL (C)KalliShuningdek, GCC tomonidan qo'llab-quvvatlanadi.
tezkor qo'ng'iroqMicrosoftECX, EDXRTL (C)KalliAgar a'zoning funktsiyasi bo'lmasa, stack-ga ko'rsatgichni qaytaring. Shuningdek, GCC tomonidan qo'llab-quvvatlanadi.
ro'yxatdan o'tishDelphi va Free PascalEAX, EDX, ECXLTR (Paskal)Kalli
bu chaqiriqWindows (Microsoft Visual C ++ )ECXRTL (C)KalliRo'yxatdan funktsiyalari uchun standart.
qo'ng'iroqWindows (Microsoft Visual C ++ )ECX, EDX, [XY] MM0-5RTL (C)KalliTez qo'ng'iroqdan kengaytirilgan. Shuningdek, ICC va Clang tomonidan qo'llab-quvvatlanadi.[9]
Watcom kompilyatoriEAX, EDX, EBX, ECXRTL (C)KalliESI-da qaytish ko'rsatkichi.
x86-64Microsoft x64 chaqiruv konvensiyasi[18]Windows (Microsoft Visual C ++, GCC, Intel C ++ kompilyatori, Delphi ), UEFIRCX / XMM0, RDX / XMM1, R8 / XMM2, R9 / XMM3RTL (C)ChaqiruvchiStek 16 baytda hizalangan. Stakda 32 baytli soya maydoni. Belgilangan 8 registrdan faqat 1 dan 4 gacha bo'lgan parametrlar uchun foydalanish mumkin. C ++ sinflari uchun maxfiy bu parametr birinchi parametr bo'lib, RCX-da uzatiladi.[26]
qo'ng'iroqWindows (Microsoft Visual C ++, Clang, ICC)RCX / [XY] MM0, RDX / [XY] MM1, R8 / [XY] MM2, R9 / [XY] MM3 + [XY] MM4-5RTL (C)ChaqiruvchiMS x64-dan kengaytirilgan.[9]
Tizim V AMD64 ABI[24]Solaris, Linux, BSD, OS X (GCC, Intel C ++ kompilyatori )RDI, RSI, RDX, RCX, R8, R9, [XYZ] MM0-7RTL (C)ChaqiruvchiStek 16 bayt chegarada hizalanadi. 128 bayt qizil zona stack ostidan. Yadro interfeysi RDI, RSI, RDX, R10, R8 va R9 dan foydalanadi. C ++ da, bu birinchi parametr.

Adabiyotlar

Izohlar

  1. ^ a b v d e Agner tuman (2010-02-16). Turli xil C ++ kompilyatorlari va operatsion tizimlari uchun konventsiyalarni chaqirish (PDF).
  2. ^ de Boyne Pollard, Jonathan (2010). "Konventsiyalarni chaqiruvchi funktsiya bo'yicha gen". Tez-tez berilgan javoblar.
  3. ^ "GCC Bugzilla - Bug 40838 - gcc stek tekislangan deb o'ylamasligi kerak". 2009.
  4. ^ "V SYSTEM V APPLICATION BINARY INTERFACE Intel 386 Architecture Processor Supplement to'rtinchi nashri" (PDF).
  5. ^ "__stdcall (C ++)". MSDN. Microsoft. Arxivlandi asl nusxasi 2008-04-10. Olingan 2019-02-13.
  6. ^ "__fastcall". MSDN. Olingan 2013-09-26.
  7. ^ Oh, Uve. "gcc atributiga umumiy nuqtai: fastcall funktsiyasi". ohse.de. Olingan 2010-09-27.
  8. ^ "Vektorli qo'ng'iroqlar konventsiyasini joriy etish'". MSDN. Olingan 2014-12-31.
  9. ^ a b v d "__vectorcall". MSDN. Olingan 2014-12-31.
  10. ^ "Clangdagi sifatlar: konventsiyalarni chaqirish". Clang hujjatlari. Olingan 8 oktyabr 2019.
  11. ^ "_vectorcall va __regcall demistified". software.intel.com. 2017 yil 7-iyun.
  12. ^ "Dastur nazorati: Ro'yxatdan o'tish konventsiyasi". docwiki.embarcadero.com. 2010-06-01. Olingan 2010-09-27.
  13. ^ "_fastcall, __fastcall". docwiki.embarcadero.com.
  14. ^ "__msfastcall". docwiki.embarcadero.com.
  15. ^ "x86 funktsiya atributlari". GNU Compiler Collection (GCC) dan foydalanish.
  16. ^ "i386: har doim regparmni yoqish".
  17. ^ "Calling_Conventions: Specifying_Calling_Conventions_the_Watcom_Way". openwatcom.org. 2010-04-27. Olingan 2018-08-31.
  18. ^ a b "x64 dasturiy ta'minot konventsiyalari: qo'ng'iroq qilish bo'yicha konventsiyalar". msdn.microsoft.com. 2010 yil. Olingan 2010-09-27.
  19. ^ "x64 Arxitektura". msdn.microsoft.com.
  20. ^ "x64 chaqiruv konvensiyasi: Qaytish qiymatlari". docs.microsoft.com. Olingan 2020-01-17.
  21. ^ "x64 dasturiy ta'minot konventsiyalari - stekni taqsimlash". Microsoft. Olingan 2010-03-31.
  22. ^ a b "Qo'ng'iroq qiluvchining / Callee saqlangan registrlari". Microsoft Docs. Microsoft.
  23. ^ "x86-64 kod modeli". Mac ishlab chiqaruvchisi kutubxonasi. Apple Inc. Arxivlandi asl nusxasidan 2016-03-10. Olingan 2016-04-06. OS X-dagi x86-64 muhitida foydalanuvchi maydoni kodi uchun faqat bitta kod modeli mavjud. Bu x86-64 System V ABI tomonidan aniqlangan kichik PIC modeliga o'xshaydi.
  24. ^ a b v d e f g h Maykl Matz; Yan Hubichka; Andreas Jeyger; va boshq., tahr. (2018-01-28). "System V Application Binary Interface: AMD64 Architecture Processor Supplement (LP64 va ILP32 Programming Models bilan) 1.0 versiyasi" (PDF). 1.0.
  25. ^ Borland C / C ++ versiyasi 3.1 Foydalanuvchilar uchun qo'llanma (PDF). Borland. 1992. 158, 189-191 betlar.
  26. ^ "Foydalanishni ro'yxatdan o'tkazish". Microsoft Docs. Microsoft. Olingan 15 sentyabr 2017.

Boshqa manbalar

Qo'shimcha o'qish