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

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

AVR регистры CPU разделены на три отдельных части, которые описаны в этой главе.

Рабочие регистры

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

Для обоих соглашений о вызовах, следующие 14 регистров могут использоваться как рабочие регистры функций:

R0-R3, R16-R23, и R30-R31

Сохраняемые регистры

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

Для обоих соглашений о вызовах, следующие сохраняемые регистры используются:

R4-R15 и R24-R27

Обратите внимание, что регистраторы R4-R15 могут быть блокированы из командной строки, и использоваться для глобальных регистровых переменных; см. -lock_regs и __regvar.

Специальные регистраторы

Для некоторых регистраторов имеются некоторые предпосылки, которые вы должны рассмотреть:

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

  • При использовании -v4 или -v6 опции процессора, регистр RAMPY - указатель на часть стека данных.

  • При использовании опции процессора, которая использует любой из регистров EIND, RAMPX, или RAMPZ, эти регистры работают как рабочие регистры.

Вызов функции

В течение вызова функции, вызываемая функция:

  • передает параметры, или в регистрах или через стек

  • помещает все остальные параметры в стек данных (CSTACK)

Управление передается вызываемой функции с адресом возврата, автоматически задвинутым в стек адреса возврата (RSTACK).

Вызываемаяфункция:

  • сохраняет любых локальные регистры необходимые функции в стеке данных

  • распределяет пространство для авто переменных и временных значений

  • продолжает выполнять непосредственно саму функцию.

Регистровые параметры против параметров стека

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

Регистровые параметры

Для обоих соглашений о вызовах, регистраторы, доступные для проходящих параметров:

R16-R23

Параметры распределяются по регистрам согласно алгоритму первого подходящего, используя требования выравнивания параметра согласно следующей таблице:

Параметр

Выравнивание

Используемые регистры

8-bit значение

1

R16, R17, R18, R19, R20, R21, R22, R23

16-bit значение

2

R17:R16, R19:R18, R21:R20, R23:R22

24-bit значение

4

R18:R17:R16, R22:R21:R20

32-bit значение

4

R19:R18:R17:R16, R23:R22:R21:R20

Назначение регистров, использующее старое соглашение о вызовах

В старом соглашении о вызовах, два крайних левых параметра передаются в регистрах, если они скалярные и до 32 битов в размере.

Следующая таблица показывает некоторых из возможных комбинаций:

Параметры

Параметр 1

Параметр 2

f(b1,b2,…)

R16

R20

f(b1,w2,…)

R16

R20, R21

f(w1,l1,…)

R16, R17

R20, R21, R22, R23

f(l1,b2,…)

R16, R17, R18, R19

R20

f(l1,l2,…)

R16, R17, R18, R19

R20, R21, R22, R23

Где b обозначает, 8-разрядный тип данных, w обозначает 16-разрядный тип данных, и l обозначает 32-разрядный тип данных. Если первый и – или второй параметр - 3-байтовый указатель, это будут пропускать в R16-R19 или R20-R22 соответственно.

Распределение регистров, использующее новое соглашение о вызовах

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

Алгоритм для назначения параметров для регистраторов - довольно сложен в новом соглашении о вызовах.

Ниже следует несколько примеров комбинаций назначения регистра. Функция с описанием (не C++):

void foo(char __far * a, int b, char c, int d)

Будет распределено как: a – в R18:R17:R16, b – в R21:R20 (требование выравнивания предотвращает R20:R19), с – в R19 (метод первого подходящего), и d – в R23:R22 (метод первого подходящего).

Другойпример:

void bar(char a, int b, long c, char d)

Это привело бы к распределению: a – в R16 (метод первого подходящего), b – в R19:R18 (выравнивание), C – в R23:R22:R21:R20 (метод первого подходящего), и d – в R17 (метод первого подходящего).

И третийпример:

voidbaz(char a, char __far * b, int c, int d)

Это дало бы следующее распределение параметров: а – в R16, b – в R22:R21:R20, с – в R19:R18, и d – в стеке.

Параметры Стека

Имеется только ограниченное число регистров, которые могут использоваться для передачи параметров. Когда нет больше доступных регистров, параметры передаются в стеке.

Кроме того, параметры передаются в стеке в следующих случаях:

  • Структурные типы: struct, union, и class если больше чем 4 байта

  • тип данных double (64-разрядные числа с плавающей запятой)

  • неименованные параметры для функций переменной длины, т.е. функции объявленные как foo (param1, ...), например printf(…).

Размещение Стека

Вызов Функции создает порядок расположения стека следующим образом:

П араметры Стека

Любые параметры, которые не вошли в регистры.

Сохраняемые регистры

R4-R15, R24-R27

Авто переменные

Область для локальных переменных.

Временная память

Любые временные значения.

Скрытые параметры

В дополнение к параметрам, видимым в функциональном объявлении и определении, также могут быть скрытые параметры:

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

  • Для не static функций члена C++, этот указатель передается как первый параметр (но помещенный после возвращения указателя на структуру, если он один). Обратите внимание, что статические функции члена не имеют указателя this.