Кіріспе
Компьютерлерде тармақшаларды шақыру жолдары
Компьютер ғылымында шақыру конвенциясы – бұл тармақшалар немесе функциялар шақырушыдан параметрлерді қалай қабылдап, нәтижені қалай қайтаратынына қатысты іске асыру деңгейіндегі (төмен деңгейлі) схема. Кез келген код функцияны шақырғанда, сол функцияға параметрлердің қайда және қалай берілетіні, ал нәтижелердің қайда және қалай қайтарылатыны туралы жобалық шешімдер қабылдалады. Мұндай дерек алмасу әдетте белгілі бір тіркегіштер арқылы немесе шақыру стегіндегі стек кадрында жүзеге асырылады. Функцияны шақыруға дайындалу және функция аяқталғаннан кейін ортаны қалпына келтіру міндеттерін шақырушы мен шақырылушы арасында қалай бөлісу жобалануының да таңдаулары бар. Кейбір шақыру конвенциялары әрбір функцияның қалай шақырылуы керектігін нақтылайды. Осы функцияларды пайдалана отырып, программаның толыққанды, дұрыс және сенімді жұмыс істеуі үшін әрбір функция шақырылымында дұрыс шақыру конвенциясы қолданылуы тиіс.
Кіріспе
Шақыру конвенциялары әдетте қолданбаның бинарлық интерфейсінің (ABI) бөлігі болып саналады. Олар шақырушы мен шақырылған функция арасындағы келісімшарт ретінде қарастырылуы мүмкін. Бұл шақыру конвенциясы "типік" ARM қосалқы бағдарламасын былай істеуге мәжбүрлейді:
Прологта r4-тен r11-ге дейінгі регистрлерді стекке салып, r14-тегі қайтару адресін де стекке салады (мұны бір STM нұсқаулығымен жасауға болады);
Берілген аргументтерді (r0-ден r3-ге дейін) жергілікті жұмыс регистрлеріне (r4-тен r11-ге дейін) көшіреді;
Қалған жергілікті жұмыс регистрлеріне (r4-тен r11-ге дейін) басқа жергілікті айнымалыларды тағайындайды;
Есептеулерді жүргізеді және қажет болған жағдайда BL арқылы басқа қосалқы бағдарламаларды шақырады, r0-ден r3-ге дейін, r12 және r14 сақталмайды деп есептейді;
Нәтижені r0 регистріне салады;
Эпилогта r4-тен r11-ге дейінгі регистрлерді стекке қайта алып, қайтару адресін бағдарлама санағышы r15-ке қайтарады. Мұны бір LDM нұсқаулығымен орындауға болады.
In the prologue, push r4 to r11 to the stack, and push the return address in r14 to the stack (this can be done with a single STM instruction);
Copy any passed arguments (in r0 to r3) to the local scratch registers (r4 to r11);
Allocate other local variables to the remaining local scratch registers (r4 to r11);
Do calculations and call other subroutines as necessary using BL, assuming r0 to r3, r12 and r14 will not be preserved;
Put the result in r0;
In the epilogue, pull r4 to r11 from the stack, and pull the return address to the program counter r15. This can be done with a single LDM instruction.
RISC-V ISA
RISC V екі нұсқадағы, қалқыма нүктелік амалдары бар немесе жоқ, анықталған шақыру конвенциясына ие. Аргументтер мүмкіндігі шектес болғанда тіркелімдер арқылы жіберіледі.
POWER, PowerPC және Power ISA
POWER, PowerPC және Power ISA архитектураларында көптеген регистрлер бар, сондықтан көптеген функциялар бір деңгейлі шақыруларда барлық аргументтерді регистрлер арқылы жіберуге мүмкіндік алады. Қосымша аргументтер стекке жіберіледі, сондай-ақ регистрлерге негізделген аргументтер үшін орын әрқашан стекте шақырылған функцияның ыңғайлылығы үшін бөлінеді, егер көп деңгейлі шақырулар (рекурсивті немесе басқа түрде) қолданылса және регистрлерді сақтау қажет болса. Бұл өзгергіш аргументтері бар функцияларда да пайдалы, мысалы, функцияның аргументтері массив ретінде қолжетімді болуы керек болғанда. Барлық процедуралық тілдер үшін бір шақыру конвенциясы қолданылады. Бранч және сілтеме нұсқаулары қайтару адресін жалпы мақсаттағы регистрлерден бөлек, арнайы сілтеме регистрінде сақтайды; процедура сілтеме регистрін мақсатты мекенжай ретінде пайдаланатын бранч нұсқауларымен шақырушысына қайта оралады. Жапырақ процедуралары сілтеме регистрін сақтау немесе қалпына келтіруді қажет етпейді; жапырақ емес процедуралар басқа процедураға шақыру жасау алдында қайтару адресін сақтау керек және оны қайтару алдында қалпына келтіру керек, сілтеме регистрін жалпы мақсаттағы регистрге көшіру үшін «Move From Special Purpose Register» нұсқауын қолдану арқылы сақтау және қажет болған жағдайда оны стекке сақтау, ал егер ол стекке сақталған болса, сақталған сілтеме регистрінің мәнін жалпы мақсаттағы регистрге жүктеу, содан кейін сақталған сілтеме регистрінің мәнін қамтитын регистрді сілтеме регистріне көшіру үшін «Move To Special Purpose Register» нұсқауын қолдану.
MIPS
O32 ABI, MIPS-тің бастапқы System V ABI-і ретінде мәртебесіне байланысты ең көп қолданылатын ABI болып табылады. Ол қатаң түрде стекке негізделген, аргументтерді беруге тек төрт регистр қолжетімді. Бұл сезілетін баяулық, сондай-ақ 16 регистрлі ескі жылжымалы нүктелік модель, көптеген басқа шақыру конвенцияларының пайда болуына себеп болды. ABI 1990 жылы қалыптасты және 1994 жылдан бері жаңартылмады. Ол тек 32 биттік MIPS үшін анықталған, бірақ GCC O64 деп аталатын 64 биттік нұсқасын жасады. 64 бит үшін, Silicon Graphics компаниясының N64 ABI (Nintendo 64-ке қатысы жоқ) көбінесе қолданылады. Ең маңызды жақсарту – аргументтерді беру үшін сегіз регистрдің қолданылуы; сонымен қатар, жылжымалы нүктелік регистрлердің саны 32-ге дейін артты. Сондай-ақ, x32 ABI-ге ұқсас, кішірек код үшін 32 биттік көрсеткіштерді пайдаланатын N32 деп аталатын ILP32 нұсқасы бар. Екеуі де процессордың 64 биттік режимінде жұмыс істейді. EABI, MIPS Technologies компаниясын қайтару мәні үшін аргументтер тізілімдерін қайта пайдаланатын радикалды "NUBI" ABI-ді ұсынуға ынталандырды. MIPS EABI-ді GCC қолдайды, бірақ LLVM қолдамайды; NUBI де қолдамайды. O32 және N32/N64-тің барлығы үшін қайтару мекенжайы тіркелімде сақталады. Бұл (секіру және сілтеме) немесе (секіру және сілтеме тіркелімі) нұсқауларын пайдалану арқылы автоматты түрде орнатылады. Стек төмен қарай өседі.
SPARC
SPARC архитектурасы, көптеген RISC архитектураларынан өзгеше, тіркелім терезелеріне негізделген. Әрбір тіркелім терезесінде 24 қолжетімді тіркелім бар: 8 "кіріс" тіркелімдері (%i0 %i7), 8 "жергілікті" тіркелімдер (%l0 %l7) және 8 "шығыс" тіркелімдері (%o0 %o7). "Кіріс" тіркелімдері функцияға аргументтерді жіберу үшін пайдаланылады, ал қалған қосымша аргументтер стекке салынуы керек. Дегенмен, шақырылған функция әрқашан ықтимал тіркелім терезесінің асығуын, жергілікті айнымалыларды және (32-биттік SPARC-те) мәні бойынша құрылымды қайтару үшін орын бөледі. Функцияны шақыру үшін, шақырылатын функцияның аргументтері "шығыс" тіркелімдеріне орналастырылады; функция шақырылғанда "шығыс" тіркелімдері "кіріс" тіркелімдеріне айналады және шақырылған функция өз "кіріс" тіркелімдеріндегі аргументтерге қол жеткізеді. Шақырылған функция жұмысын аяқтаған кезде, ол қайтарылатын мәнді бірінші "кіріс" тіркелімге орналастырады, ол шақырылған функция қайтарғанда бірінші "шығыс" тіркелімге айналады. System V ABI, көптеген қазіргі заманғы Unix-тәрізді жүйелерде қолданылатын, алғашқы алты аргументті %i0-ден %i5-ке дейінгі "кіріс" тіркелімдері арқылы жібереді, ал %i6-ны стек көрсеткіші үшін және %i7-ні қайтару мекенжайы үшін резервтейді.
Супер-Н
Windows CE 5.0 gcc Renesas R0 Қайтарым мәндерін тіркеңіз. Ассемблер псевдо-нұсқауларын кеңейту үшін уақытша. 8/16 биттік операциялар үшін жасырын бастапқы/мақсат. Сақталмайды. Қайтарым мәні, шақырушы сақтайды. Айнмалылар/уақытша. Кепілдік жоқ. R1–R3 Уақытша тіркелімдер ретінде қолданылады. Сақталмайды. Шақырушы сақтайтын аралық тіркелімдер. Құрылым мекенжайы (шақырушы сақтайды, әдепкі бойынша). Айнмалылар/уақытша. Кепілдік жоқ. R4–R7 Бұлың сан аргументтерінің алғашқы төрт сөзі. Аргумент құрастыру аймағы R4–R7 тіркелімдеріндегі аргументтерді сақтау үшін орын ұсынады. Сақталмайды. Параметрлерді жіберу, шақырушы сақтайды. Аргументтер. Кепілдік жоқ. R8–R13 Тұрақты тіркелімдер ретінде қолданылады. Сақталады. Шақырушы сақтайды. Айнмалылар/уақытша. Кепілдік бар. R14 Әдепкі фрейм көрсеткіші. (R8–R13 сондай-ақ фрейм көрсеткіші ретінде қолданылуы мүмкін, ал жапырақ процедуралары R1–R3 тіркелімдерін фрейм көрсеткіші ретінде пайдалана алады). Сақталады. Фрейм көрсеткіші, FP, шақырушы сақтайды. Айнмалылар/уақытша. Кепілдік бар. R15 Стек көрсеткіші немесе тұрақты тіркелім ретінде қолданылады. Сақталады. Стек көрсеткіші, SP, шақырушы сақтайды. Стек көрсеткіші. Кепілдік бар. Ескерту: "сақталады" шақырушыға сақтауды білдіреді; "кепілдік бар" үшін де солай.
Сызықты код
Тақырыптық код функцияны шақыруға дайындалу және шақырудан кейін тазалау жөніндегі барлық жауапкершілікті шақырылған кодқа жүктейді. Шақырушы код тек шақырылатын ішкі бағдарламалардың тізімін береді. Бұл функцияның прологы мен эпилогында – функция шақырылған көптеген орындардың орнына, функцияны орнату және тазалау кодтарын бір жерге жинақтайды. Осылайша, тақырыптық код ең ықшам шақыру конвенциясына айналады. Тақырыптық код барлық аргументтерді стек арқылы жібереді. Барлық қайтарылатын мәндер стек арқылы қайтарылады. Бұл қарапайым іске асылуды, мәндерді тіркелімдерде сақтайтын шақыру конвенцияларынан баяу етеді. Дегенмен, бірнеше жоғарғы стек мәндерін, әсіресе қайтару адресін тіркелімдерде кэштейтін тақырыптық кодтың іске асылуы, қайтару адресін әрқашан стекке итеріп шығаратын және одан алатын қосалқы бағдарламаны шақыру конвенцияларынан әдетте жылдам болады.
PL/I
PL/I тілінде жазылған бағдарламаларды шақырудың әдепкі конвенциясы барлық аргументтерді сілтеме арқылы жібереді, бірақ басқа конвенциялар да қосымша түрде көрсетілуі мүмкін. Аргументтер әртүрлі компиляторлар мен платформаларда әртүрлі өңделеді, бірақ әдетте аргументтердің жад мекенжайлары жадтағы аргументтер тізімі арқылы беріледі. Соңында, жасырылған мекенжай қайтару мәнін сақтау үшін арналған жад аймағына көрсетілуі мүмкін. PL/I тілі қолдайтын дерек типтерінің кең ауқымына байланысты, деректер сипаттамасы да берілуі мүмкін, мысалы, таңбалық немесе биттік тізбектердің ұзындығын, массивтердің өлшемдері мен шектерін (доп векторлары), немесе дерек құрылымының орналасуын және мазмұнын анықтау үшін. Тұрақты аргументтерге немесе шақырылған процедура күтетін аргумент типіне сәйкес келмейтін аргументтер үшін, формалды аргументтер жасалады.