Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Промежуточный отчёт по ассемблеру(main frame).docx
Скачиваний:
4
Добавлен:
28.08.2019
Размер:
188.13 Кб
Скачать

Соглашение о вызовах

Соглашение о вызовах - путь, которым функция в программе вызывает другую функцию. Компилятор обрабатывает это автоматически, но, если функция написана на языке ассемблеров, вы должны знать, где и как его параметры могут быть найдены, как возвратиться программе к месту вызова, и как возвратить заканчивающееся значение.

Также необходимо знать, какие регистры подпрограмма уровня ассемблера должна сохранять. Если программа сохраняет слишком много регистров, она может быть неэффективна. Если она сохраняет слишком мало регистров, результат программы может быть неправильным.

AVRIARC / C ++ Компилятор обеспечивает два соглашения о вызовах — один старый, который используется в версии 1.x компилятора, и один новый, который является заданным по умолчанию. Эта секция описывает соглашения о вызовах, используемые AVRIARC / C ++ Компилятор. Рассматриваютсяследующие элементы:

  • Выборсоглашения о вызовах

  • Объявлениефункций

  • C и C++ взаимосвязь

  • Сохранениерабочихрегистраторов

  • Функциональныйвход

  • Функциональныйвыход

  • обработкаАдресавозврата.

Выборсоглашенияо вызовах

Имеются два соглашения о вызовах:

  • старое соглашение о вызовах предлагает простой интерфейс ассемблера. Это совместимо с соглашением о вызовах, используемым в версии 1.x компилятора. Даже притом, что это соглашение не используется по умолчанию, оно рекомендует для использования при смешивании Кода ассемблера и C

  • новое соглашение о вызовах задано по умолчанию. Оно более эффективное, чем старое соглашение о вызовах, но также и более сложное, чтобы понять и может изменяться в более поздних версиях компилятора.

Новое соглашение о вызовах используется по умолчанию. Однако можно выбирать соглашение о вызовах, используя - version1_calls опция командной строки. Вы можете также объявлять, что индивидуальные функции используют старое соглашение о вызовах, используя __ version_1 функциональный атрибут, например:

extern __version_1 void doit(intarg);

Новое соглашение о вызовах очень сложно, и поэтому не рекомендовано для использования при запросе подпрограмм ассемблера. Однако, если вы намереваетесь использовать его для ваших подпрограмм ассемблера, вы должны создать файл листинга и см., как компилятор назначает различные параметры для доступных регистров.

Если будет использоваться новое соглашение о вызовах, нужно также определить значение времени выполнения модели атрибутом __rt_version используя RTMODEL директиву ассемблера:

RTMODEL "__rt_version"="value"

Значение параметра value должно иметь то же самое значение как и используемое компилятором. Для информации, относительно того, какое значение использовать, необходимо смотреть сгенерированный файл листинга. Если соглашение о вызовах изменяется в будущих версиях компилятора, образцовое значение, используемое компилятором, также изменится. Использование этого метода дает проверку последовательности модуля, поскольку компоновщик выдаст ошибку, если имеется несоответствие между значениями.

Функциональные объявления

В C, функция должна быть объявлена для компилятора, чтобы знать, как её вызвать. Объявление может быть сделано следующим образом:

inta_function(intfirst, char * second);

Это означает, что функция берет два параметра: целое число (first) и указатель на символ (second). Функция возвращает значение, целое число.

В общем случае, это единственное что известно компилятору относительно функции. Поэтому, должно способствовать выводу соглашения о вызовах из этой информации.

C и C++ написания

В C++, функция может иметь C или C++ написание. Только функции, написанные на C, могут быть осуществлены на ассемблере.

Далее приведен пример объявления функции на C:

extern "C"

{

int f(int);

}

Часто практически совместно использовать файлы заголовка между C и C++. Следующий пример показывает объявление функции написанной на C в C и C++:

#ifdef __cplusplus

extern "C"

{

#endif

int f(int);

#ifdef __cplusplus

}

#endif