Соглашение о вызовах
В информатике соглашение о вызовах — это схема уровня реализации (низкоуровневая) того, как подпрограммы или функции получают параметры от вызывающего объекта и как они возвращают результат. [1] Когда некоторый код вызывает функцию, были приняты решения о том, где и как параметры передаются в эту функцию, а также где и как результаты возвращаются из этой функции, причем эти передачи обычно выполняются через определенные регистры или внутри кадра стека при вызове. куча . Существуют варианты дизайна того, как задачи подготовки к вызову функции и восстановления среды после завершения функции распределяются между вызывающим и вызываемым объектом. Некоторые соглашения о вызовах определяют способ вызова каждой функции. Для каждого вызова функции следует использовать правильное соглашение о вызовах, чтобы обеспечить правильное и надежное выполнение всей программы с использованием этих функций.
Введение
[ редактировать ]Соглашения о вызовах обычно считаются частью двоичного интерфейса приложения (ABI). Их можно рассматривать как контракт между вызывающей стороной и вызываемой функцией. [1]
Связанные понятия
[ редактировать ]Имена или значения параметров и возвращаемых значений определяются в интерфейсе прикладного программирования (API, в отличие от ABI), который представляет собой отдельную, хотя и связанную концепцию с ABI и соглашением о вызовах. Имена членов переданных структур и объектов также будут считаться частью API, а не ABI. Иногда API включают ключевые слова для указания соглашения о вызове функций.
Соглашения о вызовах обычно не включают информацию о сроке службы динамически выделяемых структур и объектов. В другой дополнительной документации может быть указано, кто несет ответственность за освобождение выделенной памяти.
Соглашения о вызовах вряд ли будут определять расположение элементов внутри структур и объектов, например порядок байтов или упаковку структур.
Для некоторых языков соглашение о вызовах включает детали обработки ошибок или исключений (например, Go , Java ), а для других — нет (например, C++ ).
Для удаленных вызовов процедур существует аналогичная концепция, называемая маршаллингом .
конкретного языка программирования Соглашения о вызовах могут быть связаны со стратегией оценки , но чаще всего не считаются ее частью (или наоборот), поскольку стратегия оценки обычно определяется на более высоком уровне абстракции и рассматривается как часть языка, а не как часть языка. как низкоуровневая деталь реализации компилятора конкретного языка .
Различные соглашения о вызовах
[ редактировать ]Соглашения о вызовах могут отличаться:
- Где размещаются параметры. Варианты включают регистры , в стеке вызовов , сочетание того и другого или в других структурах памяти.
- Порядок передачи параметров. Варианты включают порядок слева направо, справа налево или что-то более сложное.
- функции, которые принимают переменное количество аргументов ( вариативные функции Как обрабатываются ). Опции включают только что переданные по порядку (при условии, что первый параметр находится в очевидной позиции) или переменные части массива.
- Как возвращаемые значения доставляются от вызывающего абонента обратно к вызывающему. Варианты включают в себя стек, регистр или ссылку на что-то, выделенное в куче.
- Как длинные или сложные значения обрабатываются, возможно, путем разделения на несколько регистров, внутри кадра стека или с ссылкой на память.
- Какие регистры гарантированно будут иметь то же значение при возврате вызываемого объекта, что и при вызове вызываемого объекта. Говорят, что эти регистры сохраняются или сохраняются , поэтому они не являются энергозависимыми .
- Как задача настройки и очистки после вызова функции распределяется между вызывающим и вызываемым объектом. В частности, как кадр стека , чтобы вызывающая сторона могла продолжить работу после того, как вызываемая сторона завершила работу. восстанавливается
- Передаются ли и как метаданные, описывающие аргументы
- Здесь хранится предыдущее значение указателя кадра , которое используется для восстановления кадра стека после завершения подпрограммы. Опции включаются в стек вызовов или в определенный регистр. Иногда указатели кадров вообще не используются. [2]
- Где размещаются какие-либо статические ссылки на область действия для нелокального доступа к данным подпрограммы (обычно в одной или нескольких позициях в кадре стека, но иногда в общем регистре или, для некоторых архитектур, в регистрах специального назначения)
- Для объектно-ориентированных языков способ обращения к объекту функции.
Соглашения о вызовах на одной платформе
[ редактировать ]Иногда на одной платформе появляется несколько соглашений о вызовах; данная платформа и языковая реализация могут предлагать выбор соглашений о вызовах. Причины этого включают производительность, адаптацию соглашений других популярных языков, а также ограничения или соглашения, налагаемые различными « вычислительными платформами ».
Во многих архитектурах имеется только одно широко используемое соглашение о вызовах, часто предлагаемое архитектором. Для RISC, включая SPARC, MIPS и RISC-V , часто используются имена регистров, основанные на этом соглашении о вызовах. Например, регистры MIPS $4
через $7
иметь «имена ABI» $a0
через $a3
, что отражает их использование для передачи параметров в стандартном соглашении о вызовах. (ЦП RISC имеют множество эквивалентных регистров общего назначения, поэтому обычно нет аппаратных причин давать им имена, кроме чисел.)
Соглашение о вызовах языка конкретной программы может отличаться от соглашения о вызовах базовой платформы, ОС или какой-либо библиотеки, с которой связана ссылка. Например, в 32-разрядной версии Windows вызовы операционной системы имеют соглашение о вызовах stdcall , тогда как многие C программы , которые там выполняются, используют соглашение о вызовах cdecl . Чтобы учесть эти различия в соглашении о вызовах, компиляторы часто допускают ключевые слова, определяющие соглашение о вызовах для данной функции. будут Объявления функций включать дополнительные ключевые слова, специфичные для платформы, которые указывают используемое соглашение о вызовах. При правильной обработке компилятор сгенерирует код для вызова функций соответствующим образом.
Некоторые языки позволяют явно указывать соглашение о вызове функции с помощью этой функции; в других языках будет некоторое соглашение о вызовах, но оно будет скрыто от пользователей этого языка и поэтому обычно не будет учитываться программистом.
Архитектуры
[ редактировать ]x86 (32-разрядная версия)
[ редактировать ]32-разрядная версия архитектуры x86 используется со многими различными соглашениями о вызовах. Из-за небольшого количества архитектурных регистров и исторического акцента на простоте и небольшом размере кода многие соглашения о вызовах x86 передают аргументы в стек. Возвращаемое значение (или указатель на него) возвращается в регистр. В некоторых соглашениях для первых нескольких параметров используются регистры, что может улучшить производительность, особенно для очень часто вызываемых коротких и простых листовых подпрограмм (т. е. подпрограмм, которые не вызывают другие подпрограммы).
Пример вызова:
push EAX ; pass some register result
push dword [EBP+20] ; pass some memory variable (FASM/TASM syntax)
push 3 ; pass some constant
call calc ; the returned result is now in EAX
Типичная структура вызываемого объекта: (некоторые или все (кроме ret) приведенные ниже инструкции могут быть оптимизированы с помощью простых процедур). Некоторые соглашения оставляют пространство параметров выделенным, используя обычный ret
вместо ret imm16
. В этом случае вызывающий абонент может add esp,12
в этом примере или иным образом справиться с изменением ESP.
calc:
push EBP ; save old frame pointer
mov EBP,ESP ; get new frame pointer
sub ESP,localsize ; reserve stack space for locals
.
. ; perform calculations, leave result in EAX
.
mov ESP,EBP ; free space for locals
pop EBP ; restore old frame pointer
ret paramsize ; free parameter space and return.
х86-64
[ редактировать ]В 64-битной версии архитектуры x86, известной как x86-64 , AMD64 и Intel 64, обычно используются две последовательности вызовов. В Windows используется одна последовательность вызовов, определенная Microsoft; другая последовательность вызовов, указанная в AMD64 System V ABI, используется Unix-подобными системами и, с некоторыми изменениями, OpenVMS . Поскольку x86-64 имеет больше регистров общего назначения, чем 16-битный x86, оба соглашения передают некоторые аргументы в регистрах.
АРМ (А32)
[ редактировать ]Стандартное 32-битное соглашение о вызовах ARM распределяет 16 регистров общего назначения следующим образом:
- r15: Счетчик программ (согласно спецификации набора команд).
- r14: Регистр связи. Инструкция BL, используемая при вызове подпрограммы, сохраняет адрес возврата в этом регистре.
- r13: Указатель стека. Инструкции Push/Pop в режиме работы «Thumb» используют только этот регистр.
- r12: Рабочий регистр внутрипроцедурного вызова.
- от r4 до r11: локальные переменные.
- от r0 до r3: значения аргументов, передаваемые в подпрограмму, и результаты, возвращаемые из подпрограммы.
Если тип возвращаемого значения слишком велик, чтобы поместиться в от r0 до r3, или его размер не может быть определен статически во время компиляции, то вызывающая сторона должна выделить место для этого значения во время выполнения и передать указатель на это пространство в r0.
Подпрограммы должны сохранять содержимое от r4 до r11 и указатель стека (возможно, сохраняя их в стек в прологе функции , затем используя их как рабочее пространство, а затем восстанавливая их из стека в эпилоге функции ). В частности, подпрограммы, вызывающие другие подпрограммы, должны сохранить адрес возврата в регистре связи r14 в стеке перед вызовом этих других подпрограмм. Однако таким подпрограммам не требуется возвращать это значение в r14 — им просто нужно загрузить это значение в r15, программный счетчик, чтобы вернуться.
Соглашение о вызовах ARM требует использования полного нисходящего стека. Кроме того, указатель стека всегда должен быть выровнен по 4 байтам и всегда должен быть выровнен по 8 байтам при вызове функции с открытым интерфейсом. [3]
Это соглашение о вызовах приводит к тому, что «типичная» подпрограмма ARM:
- В прологе поместите r4 в r11 в стек и поместите адрес возврата в r14 в стек (это можно сделать с помощью одной инструкции STM);
- Скопируйте все переданные аргументы (от r0 до r3) в локальные временные регистры (от r4 до r11);
- Назначьте другие локальные переменные оставшимся локальным временным регистрам (от r4 до r11);
- Выполните вычисления и при необходимости вызовите другие подпрограммы с помощью BL, предполагая, что от r0 до r3, r12 и r14 не будут сохранены;
- Поместите результат в r0;
- В эпилоге вытащите из стека r4 в r11 и вытащите адрес возврата в программный счетчик r15. Это можно сделать с помощью одной инструкции LDM.
АРМ (А64)
[ редактировать ]Соглашение о вызовах 64-битного ARM ( AArch64 ) распределяет 31 регистр общего назначения следующим образом: [4]
- x31 (SP): указатель стека или нулевой регистр, в зависимости от контекста.
- x30 (LR): регистр связи процедур, используемый для возврата из подпрограмм.
- x29 (FP): указатель кадра.
- от x19 до x28: вызов сохранен.
- x18 (PR): Регистр платформы. Используется для некоторых специальных целей, специфичных для операционной системы, или для дополнительного регистра, сохраняемого вызывающим абонентом.
- x16 (IP0) и x17 (IP1): рабочие регистры внутрипроцедурного вызова.
- От x9 до x15: локальные переменные, вызывающий абонент сохранен.
- x8 (XR): Косвенный адрес возвращаемого значения.
- от x0 до x7: значения аргументов, передаваемые подпрограмме, и результаты, возвращаемые из нее.
Все регистры, начинающиеся с x, имеют соответствующий 32-битный регистр с префиксом w . Таким образом, 32-битный x0 называется w0.
Аналогично, 32 регистра с плавающей запятой распределяются следующим образом: [5]
- от v0 до v7: значения аргументов, передаваемые подпрограмме, и результаты, возвращаемые из нее.
- v8–v15: сохраняется вызываемый абонент, но необходимо сохранить только нижние 64 бита.
- v16–v31: локальные переменные, вызывающая сторона сохранена.
RISC-V ISA
[ редактировать ]RISC-V имеет определенное соглашение о вызовах с двумя вариантами: с плавающей запятой или без нее. [6] Он передает аргументы в регистры, когда это возможно.
POWER, PowerPC и Power ISA
[ редактировать ]Архитектуры POWER , PowerPC и Power ISA имеют большое количество регистров, поэтому большинство функций могут передавать все аргументы в регистры для одноуровневых вызовов. Дополнительные аргументы передаются в стек, и место для аргументов на основе регистров также всегда выделяется в стеке для удобства вызываемой функции в случае, если используются многоуровневые вызовы (рекурсивные или иные) и регистры необходимо сохранить. Это также используется в вариативных функциях , таких как printf()
, где к аргументам функции необходимо обращаться как к массиву. Для всех процедурных языков используется единое соглашение о вызовах.
Инструкции ветвления и связи сохраняют адрес возврата в специальном регистре связи, отдельном от регистров общего назначения; процедура возвращается вызывающей стороне с инструкцией ветвления, которая использует регистр связи в качестве адреса назначения. Листовым процедурам не требуется сохранять или восстанавливать регистр связи; неконечные подпрограммы должны сохранять адрес возврата перед вызовом другой подпрограммы и восстанавливать его перед возвратом, сохраняя его с помощью команды «Переместить из регистра специального назначения», чтобы переместить регистр связи в регистр общего назначения и, при необходимости, затем сохранить его в стек и восстановить, если оно было сохранено в стеке, загрузив сохраненное значение регистра связи в регистр общего назначения, а затем используя команду «Переместить в регистр специального назначения» для перемещения регистра, содержащего сохраненную информацию. значение регистра связи в регистр связи.
МИПС
[ редактировать ]О32 [7] ABI является наиболее часто используемым ABI благодаря своему статусу исходного ABI System V для MIPS. [8] Он основан строго на стеке, всего с четырьмя регистрами. $a0-$a3
доступен для передачи аргументов. Эта кажущаяся медлительность, а также устаревшая модель с плавающей запятой, состоящая всего из 16 регистров, способствовали распространению многих других соглашений о вызовах. ABI сформировался в 1990 году и никогда не обновлялся с 1994 года. Он определен только для 32-битного MIPS, но GCC создал 64-битный вариант под названием O64. [9]
N64 ABI (не связанный с Nintendo 64 Для 64-разрядной версии чаще всего используется ) от Silicon Graphics. Самым важным улучшением является то, что теперь для передачи аргументов доступны восемь регистров; Это также увеличивает количество регистров с плавающей запятой до 32. Существует также версия ILP32 под названием N32, которая использует 32-битные указатели для меньшего кода, аналогично x32 ABI . Оба работают в 64-битном режиме процессора. [9]
Было предпринято несколько попыток заменить O32 32-битным ABI, который больше напоминает N32. На конференции 1995 года был предложен MIPS EABI, 32-битная версия которого была очень похожа. [10] EABI вдохновил MIPS Technologies предложить более радикальный ABI «NUBI», который дополнительно повторно использует регистры аргументов для возвращаемого значения. [11] MIPS EABI поддерживается GCC, но не LLVM; ни один из них не поддерживает NUBI.
Для всех O32 и N32/N64 адрес возврата хранится в $ra
зарегистрироваться. Это устанавливается автоматически с помощью JAL
(перейти и связать) или JALR
(регистрация перехода и соединения). Стек растет вниз.
СПАРК
[ редактировать ]Архитектура SPARC , в отличие от большинства RISC -архитектур, построена на окнах регистров . В каждом окне регистров имеется 24 доступных регистра: 8 — «входящие» регистры (%i0-%i7), 8 — «локальные» регистры (%l0-%l7) и 8 — «выходящие» регистры (% о0-%о7). Регистры «in» используются для передачи аргументов вызываемой функции, а любые дополнительные аргументы необходимо помещать в стек . Однако вызываемая функция всегда выделяет пространство для обработки потенциального переполнения окна регистра, локальных переменных и (в 32-битном SPARC) возврата структуры по значению. Чтобы вызвать функцию, аргументы вызываемой функции помещаются в «выходные» регистры; когда функция вызывается, «выходные» регистры становятся «входящими» регистрами, и вызываемая функция получает доступ к аргументам в своих «входящих» регистрах. Когда вызываемая функция завершается, она помещает возвращаемое значение в первый входной регистр, который становится первым выходным регистром при завершении вызванной функции.
Система V ABI , [12] которому следуют большинство современных Unix -подобных систем, передает первые шесть аргументов в «входящие» регистры от %i0 до %i5, резервируя %i6 для указателя кадра и %i7 для адреса возврата.
IBM System/360 и его преемники
[ редактировать ]IBM System/360 — это еще одна архитектура без аппаратного стека. Приведенные ниже примеры иллюстрируют соглашение о вызовах, использовавшееся в OS/360 и его преемниках до появления 64-разрядной версии z/Architecture ; другие операционные системы для System/360 могут иметь другие соглашения о вызовах.
Вызов программы:
LA 1,ARGS Load argument list address L 15,=A(SUB) Load subroutine address BALR 14,15 Branch to called routine1 ... ARGS DC A(FIRST) Address of 1st argument DC A(SECOND) ... DC A(THIRD)+X'80000000' Last argument2
Вызываемая программа:
SUB EQU * This is the entry point of the subprogram
Стандартная последовательность ввода:
USING *,153 STM 14,12,12(13) Save registers4 ST 13,SAVE+4 Save caller's savearea addr LA 12,SAVE Chain saveareas ST 12,8(13) LR 13,12 ...
Стандартная последовательность возврата:
L 13,SAVE+45 LM 14,12,12(13) L 15,RETVAL6 BR 14 Return to caller SAVE DS 18F Savearea7
Примечания:
- The
BALR
Инструкция сохраняет адрес следующей инструкции (адрес возврата) в регистре, указанном первым аргументом (регистр 14), и переходит к адресу второго аргумента в регистре 15. - Вызывающая сторона передает адрес списка адресов аргументов в регистр 1. В последнем адресе установлен старший бит, обозначающий конец списка. Это ограничивает программы, использующие это соглашение, 31-битной адресацией.
- Адрес вызываемой процедуры находится в регистре 15. Обычно он загружается в другой регистр, и регистр 15 не используется в качестве базового регистра.
- The
STM
инструкция сохраняет регистры 14, 15 и от 0 до 12 в 72-байтовой области, предоставленной вызывающей стороной, называемой областью сохранения, на которую указывает регистр 13. Вызываемая процедура предоставляет свою собственную область сохранения для использования подпрограммами, которые она вызывает; адрес этой области обычно хранится в регистре 13 на протяжении всей процедуры. Следующие инструкцииSTM
обновить прямую и обратную цепочки, связывающие эту область сохранения с областью сохранения вызывающего абонента. - Последовательность возврата восстанавливает регистры вызывающей стороны.
- Регистр 15 обычно используется для передачи возвращаемого значения.
- Объявление
savearea
статически в вызываемой подпрограмме делает ее нереентерабельной и нерекурсивной ; реентерабельная программа использует динамическийsavearea
, полученный либо из операционной системы и освобожденный при возврате, либо в памяти, переданной вызывающей программой.
В системе/390 ABI [13] и z/Architecture ABI, [14] используется в Linux:
- Регистры 0 и 1 энергозависимы.
- Регистры 2 и 3 используются для передачи параметров и возвращаемых значений.
- Регистры 4 и 5 также используются для передачи параметров.
- Регистр 6 используется для передачи параметров и должен быть сохранен и восстановлен вызываемой стороной.
- Регистры с 7 по 13 предназначены для использования вызываемым абонентом и должны быть им сохранены и восстановлены.
- Регистр 14 используется для обратного адреса.
- Регистр 15 используется как указатель стека.
- Регистры с плавающей запятой 0 и 2 используются для передачи параметров и возвращаемых значений.
- Регистры с плавающей запятой 4 и 6 предназначены для использования вызываемым абонентом и должны быть им сохранены и восстановлены.
- В z/Architecture регистры с плавающей запятой 1, 3, 5 и с 7 по 15 предназначены для использования вызываемым объектом.
- Регистр доступа 0 зарезервирован для использования системой.
- Регистры доступа с 1 по 15 предназначены для использования вызываемым абонентом.
Дополнительные аргументы передаются в стек.
СуперХ
[ редактировать ]Зарегистрироваться | Windows CE 5.0 | GCC | Ренесас |
---|---|---|---|
Р0 | Возвращаемые значения. Временно для расширения псевдоинструкций сборки. Неявный источник/назначение для 8/16-битных операций. Не сохранилось. | Возвращаемое значение, вызывающий абонент сохраняет | Переменные/временные. Не гарантировано |
Р1..Р3 | Служит временными регистрами. Не сохранилось. | Звонивший сохранил царапину. Адрес структуры (сохранение звонящего по умолчанию) | Переменные/временные. Не гарантировано |
Р4..Р7 | Первые четыре слова целочисленных аргументов. Область построения аргументов обеспечивает пространство, в которое могут попасть аргументы, содержащие R4–R7. Не сохранилось. | Передача параметров, сохранение вызывающего абонента | Аргументы. Не гарантировано. |
Р8..Р13 | Служит постоянными регистрами. Сохранено. | Вызов сохранений | Переменные/временные. Гарантировано. |
Р14 | Указатель кадра по умолчанию. (R8-R13 также может служить указателем кадра, а конечные процедуры могут использовать R1-R3 в качестве указателя кадра.) Сохраняется. | Указатель кадра, FP, сохранение вызовов | Переменные/временные. Гарантировано. |
15 рэндов | Служит указателем стека или постоянным регистром. Сохранено. | Указатель стека, SP, сохранение вызываемого абонента | Указатель стека. Гарантировано. |
Примечание: «сохраненные» резервы для сохранения вызываемого абонента; то же самое касается и «гарантированного».
68 тыс.
[ редактировать ]Наиболее распространенное соглашение о вызовах для серии Motorola 68000 : [15] [16] [17] [18]
- d0, d1, a0 и a1 — рабочие регистры.
- Все остальные регистры сохраняются вызываемым абонентом.
- a6 — указатель кадра, который можно отключить с помощью опции компилятора.
- Параметры помещаются в стек справа налево.
- Возвращаемое значение сохраняется в d0.
ИБМ 1130
[ редактировать ]IBM 1130 представлял собой небольшую 16-битную машину с пословной адресацией. В нем было всего шесть регистров плюс индикаторы состояния и не было стека. Регистрами являются регистр адреса инструкции (IAR) , аккумулятор (ACC) , расширение аккумулятора (EXT) и три индексных регистра X1–X3. Вызывающая программа отвечает за сохранение ACC, EXT, X1 и X2. [19] Есть две псевдооперации для вызова подпрограмм: CALL
кодировать неперемещаемые подпрограммы, напрямую связанные с основной программой, и LIBF
для вызова подпрограмм перемещаемой библиотеки через вектор передачи . [20] Обе псевдооперации разрешаются в IAR Branch и Store ( BSI
) машинная инструкция, которая сохраняет адрес следующей инструкции по ее эффективному адресу (EA) и переходит к EA+1.
Аргументы следуют за BSI
—обычно это адреса аргументов, состоящие из одного слова—вызываемая подпрограмма должна знать, сколько аргументов ожидать, чтобы она могла пропустить их при возврате. Альтернативно аргументы могут передаваться в регистрах. Подпрограммы функций возвращали результат в ACC для реальных аргументов или в ячейку памяти, называемую псевдоаккумулятором действительных чисел (FAC). Аргументы и адрес возврата были адресованы с использованием смещения значения IAR, хранящегося в первом месте подпрограммы.
* 1130 subroutine example ENT SUB Declare "SUB" an external entry point SUB DC 0 Reserved word at entry point, conventionally coded "DC *-*" * Subroutine code begins here * If there were arguments the addresses can be loaded indirectly from the return address LDX I 1 SUB Load X1 with the address of the first argument (for example) ... * Return sequence LD RES Load integer result into ACC * If no arguments were provided, indirect branch to the stored return address B I SUB If no arguments were provided END SUB
Подпрограммы в IBM 1130, CDC 6600 и PDP-8 (все три компьютера были представлены в 1965 году) хранят обратный адрес в первом месте подпрограммы. [21]
Соглашения о вызовах вне машинной архитектуры
[ редактировать ]Резьбовой код
[ редактировать ]Многопоточный код возлагает всю ответственность за настройку и очистку после вызова функции на вызываемый код. Вызывающий код ничего не делает, а лишь выводит список вызываемых подпрограмм. Это помещает весь код настройки и очистки функции в одно место — пролог и эпилог функции — а не во многих местах, где функция вызывается. Это делает многопоточный код наиболее компактным соглашением о вызовах.
Поточный код передает все аргументы в стек. Все возвращаемые значения возвращаются в стек. Это делает наивные реализации медленнее, чем соглашения о вызовах, которые сохраняют больше значений в регистрах. Однако реализации многопоточного кода, которые кэшируют в регистрах несколько значений верхнего уровня стека, в частности адрес возврата, обычно работают быстрее, чем соглашения о вызове подпрограмм, которые всегда помещают и извлекают адрес возврата в стек. [22] [23] [24]
ПЛ/Я
[ редактировать ]Соглашение о вызовах по умолчанию для программ, написанных на языке PL/I, передает все аргументы по ссылке , хотя при желании можно указать и другие соглашения. Аргументы обрабатываются по-разному для разных компиляторов и платформ, но обычно адреса аргументов передаются через список аргументов в памяти. Может быть передан окончательный скрытый адрес, указывающий на область, содержащую возвращаемое значение. Из-за большого разнообразия типов данных, поддерживаемых PL/I, дескриптор данных также может передаваться для определения, например, длины символьных или битовых строк, размера и границ массивов ( дополнительных векторов ) или макета и содержимого. структуры данных . Фиктивные аргументы создаются для аргументов, которые являются константами или не соответствуют типу аргумента, ожидаемого вызываемой процедурой.
См. также
[ редактировать ]Ссылки
[ редактировать ]- ^ Перейти обратно: а б «Соглашения о вызовах» . cs.cornell.edu . Проверено 5 марта 2024 г.
- ^ «/Oy (пропуск указателя кадра)» . Learn.microsoft.com . 3 августа 2021 г. Проверено 14 июня 2024 г.
- ^ «Стандарт вызова процедур для архитектуры ARM» . 2021.
- ^ «Параметры в регистрах общего назначения» . Руководство программиста серии ARM Cortex-A для ARMv8-A . Проверено 12 ноября 2020 г.
- ^ «Параметры в NEON и регистрах с плавающей запятой» . Developer.arm.com . Проверено 13 ноября 2020 г.
- ^ «Соглашение о вызовах RISC-V» (PDF) .
- ^ «Краткий справочник по набору инструкций MIPS32» .
- ^ Свитмен, Доминик. См. MIPS Run (2-е изд.). Издательство Морган Кауфманн . ISBN 0-12088-421-6 .
- ^ Перейти обратно: а б «История MIPS ABI» .
- ^ Кристофер, Эрик (11 июня 2003 г.). "Документация mips eabi" . [электронная почта защищена] (список рассылки) . Проверено 19 июня 2020 г.
- ^ "КЛУБ "
- ^ Дополнение к процессору SPARC для бинарного интерфейса приложения System V (3-е изд.).
- ^ «Дополнение к двоичному интерфейсу приложения S / 390 ELF» .
- ^ «Дополнение к двоичному интерфейсу приложения zSeries ELF» .
- ^ Смит, доктор Майк. «Сравнение регистров SHARC (21k) и 68k» .
- ^ XGCC: Языковая система Gnu C/C++ для разработки встраиваемых систем (PDF) . Корпорация инструментов встроенной поддержки. 2000. с. 59.
- ^ «COLDFIRE/68K: ThreadX для семейства Freescale ColdFire» . Архивировано из оригинала 2 октября 2015 г.
- ^ Мошовос, Андреас. «Продолжение подпрограмм: передача аргументов, возврат значений и распределение локальных переменных» .
все регистры, кроме d0, d1, a0, a1 и a7, должны сохраняться во время вызова.
- ^ Корпорация IBM (1967). Система IBM 1130 Disk Monitor, версия 2. Введение в систему (C26-3709-0) (PDF) . п. 67 . Проверено 21 декабря 2014 г.
- ^ Корпорация IBM (1968). Язык ассемблера IBM 1130 (C26-5927-4) (PDF) . стр. 24–25.
- ^ Смотерман, Марк (2004). «Поддержка вызовов подпрограмм и процедур: Ранняя история» .
- ^ Родригес, Брэд. «Движение вперед, часть 1: проектные решения в ядре Forth» .
На 6809 или Zilog Super8 DTC работает быстрее, чем STC.
- ^ Эртль, Антон. «Скорость различных методов отправки переводчиков» .
- ^ Залески, Мэтью (2008). «Глава 4: Разработка и реализация эффективной интерпретации» . YETI: постепенно расширяемый интерпретатор трассировок .
Хотя известно, что интерпретаторы с прямым потоком имеют плохие свойства прогнозирования ветвления... задержка вызова и возврата может быть больше, чем при косвенном переходе.
Внешние ссылки
[ редактировать ]- Джонсон, Стивен Кертис ; Ричи, Деннис Макалистер (сентябрь 1981 г.). «Технический отчет по информатике № 102: Последовательность вызовов языка C» . Лаборатории Белла .
- Введение в сборку на PowerPC
- Руководство по вызову функций ABI в Mac OS X
- Стандарт вызова процедур для архитектуры ARM
- Программирование встраиваемых систем с помощью GNU Toolchain, раздел 10. Запуск C.