Как я обошелся с верхними регистрами

Не знаю насколько пригодится эта придумка, но мне показалось удобным:

Мы имеем 10 регистров, от R16 до R25, которые «лучше чем остальные», ибо в них можно пихать
константы. То есть их удобно использовать как промежуточные при вычислениях. А чтобы не сохраняться в стеке при вызове прерываний, можно отдать 4 регистра на откуп обработчикам прерываний — то есть просто условиться для себя, что вот эти 4 регистра юзаем ТОЛЬКО в прерываниях.

Вот так:

.def TMPI0 = R16;
.def TMPI1 = R17
.def TMPI2 = R18
.def TMPI3 = R19

Остальные 6 я поделил так

Вот так:

.def TMP0 = R20; TMP0-TMP3 — для всяких 8-битных вычислений
.def TMP1 = R21;
.def TMP2 = R22; TMP_LOL — TMP_HOH — для 16 и 32 битных,
.def TMP3 = R23;
.def TMP_LOL = R22;
.def TMP_HOL = R23;
.def TMP_LOH = R24;
.def TMP_HOH = R25;
.def NULL = R5; ну и нолик вечный, инициализируем нулем в начале, и более
на запись не трогаем.

Вряд ли я открыл Америку, скорее изобрел очередной велик, но определенный порядок в голове и в коде появился. А то все эти LDI R16, CPI R21, R22 — очень тяжелочитабельны.

Комментарии (16)

RSS свернуть / развернуть
Это не ново, да.
А чем регистры 16-25 особенные? Ассемблер и архитектуру АВР я пока еще особо не вкуривал.
0
  • avatar
  • Vga
  • 14 марта 2011, 17:40
«Особенные» не они, а регистры 0-16. С ними не работают некоторые очень удобные команды. Например вместо:
ldi R17, 0x38 ; Запихать число 0x38 в R17

для младших регистров приходится писать:
ldi R16, 0x38 ; Сначала пихаем число во временный регистр (любой из 16-31)
mov R5, r16 ; А потом уже перемещаем в R5

А регистры R26:R27 R28:R29 и R30:R31 — это двойные (1и битные) регистры X Y Z
0
Так вот почему компиляторы так любят R16 и R17…
0
у меня и написано «можно пихать константы»:-)) Т.е. насколько я понимаю в логической структуре МК младшие регистры не подключены к какой-то сущности, через которую из программного кода лезут константы. Т.е. не работают команды с младшими те, что работают с константами — LDI, CPI, SUBI итд
0
На самом деле скорее всего им просто не хватило бита. Врядли ошибусь, если предположу что в этих командах (а команды у АВР ЕМНИП фиксированные 2-байтные) выделено 4 бита на код команды, 4 на регистр (итого адресация 4-х регистров) и байт под собственно константу. Хорошо еще что они не ограничили команду 8-ю верхними (почему верхними — тоже понятно, для адресных регистров XYZ загрузка констант весьма актуальна) :)
0
Тьфу, адресация 16-ти регистров.
0
Есть мнение, что это связано с записью команды в флеш-памяти. Команда всегда имеет размер 16 бит (кроме, ЕМНИП, jmp и call). Туда надо упихать идентификатор команды и операнды. Так-как в LDI второй операнд — целый байт, приходится урезать размер для первого операнда. Наверное урезали до 4х бит. Получается всего 16 комбинаций — 16 регистров.

Правда хз, почему выбрали старшие…
0
А JMP и CALL больше? Адрес же содержат относительные переходы, а абсолютные прыгают по адресу в Z.
А вообще, то, что они впихали столько команд в 16 бит — впечатляет.
0
Эти по 4 байта.
Относительные это rjmp и rcall. Они могут прыгать на 4к туда и обратно.

Вот тут есть справочник по командам:
0
0
Такое и в даташите есть. Но размер CALL и JMP не указан.
0
.def NULL = R0; ну и нолик вечный, инициализируем нулем в начале, и более
на запись не трогаем.
Не надо так категорично, трогаем на запись после команд умножения, команд LPM и SPM.
0
  • avatar
  • John
  • 14 марта 2011, 17:52
LPM может выгружать данные в любой регистр.
0
Их всего шесть команд: LPM; LPM Rd,Z; LPM Rd,Z+; ELPM; ELPM Rd,Z и ELPM Rd,Z+. Я имел в виду LPM и ELPM. В любой регистр выгрузить не всегда получится, например, ATtiny28 знает только первую из этих команд.
0
Блин, лоханулся, СПАСИБО!!! заюзаю другой какойнить:-)
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.