ARM регистры
ARM предлагает шестнадцать регистров, от R0 до R15. Все регистры представляют собой 32-битные значения. Из этих регистров только два имеют конкретное назначение.
- R15 - это программный счетчик.
- R14 устанавливается в адрес возврата при выполнении инструкции BL.
Если вы пишете программы для пользовательского режима: это, плюс применимые соглашения, - почти все, что вам нужно знать.
Полный набор регистров
Однако на самом деле ARM предлагает тридцать семь регистров. Тридцать из них - это регистры общего назначения, названные от R0 до R14. Это возможно, потому что то, какие регистры вы видите, зависит от того, в каком режиме процессора вы находитесь. Затем идет R15, программный счетчик. Остальные шесть регистров - это регистры состояния, и их видимость зависит от текущего режима работы процессора.
В общем случае R0 - R12 одинаковы, за исключением режима FIQ, где R8 и выше являются теневыми регистрами.
R13 и R14 меняются в зависимости от режима работы процессора, за исключением двух самых низкопривилегированных (User и System). Этот регистр является банковским для всех режимов (кроме System), чтобы позволить каждому режиму иметь свой собственный стек.
Аналогично банкуется и R14, так что если программа режима User вызывает функцию режима System при возникновении прерывания, которая сама прерывается FIQ... все они номинально будут помещать свои адреса возврата в R14, однако, поскольку в каждом случае это банкованный R14, все не развалится.
Для обработки FIQ регистры R8 и выше являются частными, так что регистры могут быть установлены и сохранены между FIQ, и обработка может начаться без необходимости загрузки регистров из памяти.
Регистр состояния CPSR одинаков для всех режимов, однако все режимы, кроме User и System, вводят регистр состояния SPSR, который специфичен для данного режима.
Диаграмма должна сделать это более понятным. Таблица регистров ARM и их распределение по режимам.
| Регистр | Пользователь | Система | Супервизор | Прерывание | Неопределённый | IRQ | FIQ |
|---|---|---|---|---|---|---|---|
| R0 | |||||||
| R1 | |||||||
| R2 | |||||||
| R3 | |||||||
| R4 | |||||||
| R5 | |||||||
| R6 | |||||||
| R7 | |||||||
| R8 | R8_fiq | ||||||
| R9 | R9_fiq | ||||||
| R10 | R10_fiq | ||||||
| R11 | R11_fiq | ||||||
| R12 | R12_fiq | ||||||
| R13 | R13_svc | R13_abt | R13_und | R13_irq | R13_fiq | ||
| R14 | R14_svc | R14_abt | R14_und | R14_irq | R14_fiq | R15 |
Именование регистров APCS
Стандарт вызова процедур Arm определяет имена для различных регистров следующим образом:
| Регистр | Название в APC | Назначение |
|---|---|---|
| R0 | a1 | Регистр аргументов, передача значений. Не требует сохранения между вызовами. Результаты функций обычно возвращаются в R0. |
| R1 | a2 | Переменные регистры, используются внутри функций. Если используются, должны сохраняться. |
| R2 | a3 | Лимит стека / дескриптор фрагмента стека. |
| R3 | a4 | Указатель фрейма (Frame Pointer). Содержит ноль или указывает на структуру стека для трассировки. |
| R4 | v1 | Временное рабочее пространство при входе в процедуру. |
| R5 | v2 | Указатель стека (Stack Pointer). Полностью нисходящий стек, указывает на нижнюю свободную ячейку. |
| R6 | v3 | Регистр связи (Link Register). Содержит адрес возврата при выходе из функции. |
| R7 | v4 | Счётчик команд (Program Counter). |
По возвращении функции (при заталкивании lr в pc) v1-v6, sl, fp и sp должны быть теми же, что и при входе.
Оригинальный стандарт APCS определен в Справочном руководстве программиста RISC OS на стр. 4-399.
26-битная операция
Оригинальные ARM (ARM2, ARM3) были более простыми и поддерживали только четыре режима работы процессора с соответственно меньшим количеством регистров.
26 бит" в названии обусловлено тем, что ширина программного счетчика составляет всего 26 бит, что позволяет R15 хранить также флаги состояния. Хотя эта система работала хорошо и позволяла одной простой инструкцией восстановить все стековые регистры и выйти из функции, она была сильно ограничена тем фактом, что 26 бит позволяют адресовать только 64 Мбайт. Когда ARM был разработан в конце 80-х, это был огромный объем памяти - на самом деле ни один MEMC (чип контроллера памяти) не способен адресовать более 4MiB, а поскольку использование нескольких MEMC часто было причудливым, большинство машин Archimedes содержат не более 4MiB, и я не видел ни одной с более чем 8MiB. Максимально возможным является 16 Мбайт (с четырьмя MEMC), как из-за аппаратных ограничений, так и из-за того, что взгляд MEMC на мир разделяет 64 Мбайт памяти на 32 Мбайт логически отображаемой памяти, 16 Мбайт физически отображаемой памяти и 16 Мбайт "прочего" (ввод/вывод и чтение:ROM, запись:VIDC/MEMC/AddressTranslation).
Для машин RISC OS эпохи Acorn набор регистров выглядит следующим образом:
| Регистр | Пользовательский (User) | Супервизор (Supervisor) | IRQ | FIQ |
|---|---|---|---|---|
| R0 | R0 | — | — | — |
| R1 | R1 | — | — | — |
| R2 | R2 | — | — | — |
| R3 | R3 | — | — | — |
| R4 | R4 | — | — | — |
| R5 | R5 | — | — | — |
| R6 | R6 | — | — | — |
| R7 | R7 | — | — | — |
| R8 | R8 | — | — | R8_fiq |
| R9 | R9 | — | — | R9_fiq |
| R10 | R10 | — | — | R10_fiq |
| R11 | R11 | — | — | R11_fiq |
| R12 | R12 | — | — | R12_fiq |
| R13 | R13 | R13_svc | R13_irq | R13_fiq |
| R14 | R14 | R14_svc | R14_irq | R14_fiq |
| R15 | PC + PSR |
Поскольку процессоры RiscPC работают в 26-битном и 32-битном режимах (чтобы можно было использовать более 64 Мбайт), все несколько сложнее. Однако, как конечный пользователь, вы можете предположить, что версии RISC OS ниже RISC OS 5 будут работать в 26-битном режиме (с отдельными задачами, ограниченными объемом памяти, к которой можно обратиться). Тем не менее, если вы планируете писать в режиме IRQ или FIQ, вам придется прочитать соответствующее Техническое справочное руководство.
RISC OS 5 (Iyonix, Beagle Board и т.д.) работает в 32-битной среде, поэтому данный раздел к ней не относится. Аналогичным образом, я считаю, что RISC OS 6 работает в аналогичной среде. Обратите внимание, что RISC OS 6 является развитием RISC OS 4 от RISC OS Ltd. и представляет собой другую ветвь, а значит, не связана с RISC OS 5 от Castle. Именно RISC OS 5 получила открытый исходный код.
В качестве примера приведем небольшую причудливую программу для перехода в 32-битный режим (в основном в 26-битной RISC OS), установки флага Z, возврата в 26-битный режим и проверки, установлен ли флаг Z. Программа должна работать на RiscPC, A7000(+), Mico и т.д. под управлением RISC OS версии 3.5, 3.6, 3.7 или одной из семейства RISC OS 4 Select/Adjust. Она не будет работать на Iyonix или аналогичных/поздних версиях.
REM >32bittest
REM
REM Short example to go into 32 bit mode, set the
REM Z flag, and return to a conditional based upon
REM this.
REM
REM From: https://upread.ru/
REM
REM Нам нужно убедиться в наличии необходимого оборудования...
emsg$ = "Sorry, you'll need a RiscPC or later, with a 32 bit capable "
emsg$+= "processor in order to use this software."
ON ERROR SYS "OS_PrettyPrint", emsg$ : PRINT : END
SYS "OS_Memory", 6
REM ?? Как обнаружить и исправить слишком поздние машины, т.е. Iyonix?
ON ERROR PRINT REPORT$+" at "+STR$(ERL/10) : END
DIM code% 1024
PRINT "Assembling code"
FOR l% = 0 TO 2 STEP 2
P% = code%
[ OPT l%
EXT 1 ; Включить ExtBASICAsm
\ Сохраняем наш R14 и переходим в режим SVC
STMFD R13!, {R14}
SWI "OS_EnterOS"
ADR R0, entering
SWI "OS_Write0"
SWI "OS_NewLine"
\ Выключите все прерывания, потому что RISC OS не будет ожидать 32-битного режима!
SWI "OS_IntOff"
\ User32 code
MOV R0, #%10011
MSR CPSR_all, R0 ; Выберите режим CPSR, очистите все биты
MOV R0, R0
MRS R0, CPSR_all ; Считать CPSR
BIC R0, R0, #&F0000000 ; Очистить биты флага
BIC R0, R0, #&1F ; Очистить биты режима
ORR R0, R0, #1<<30 ; Установить флаг Z
ORR R0, R0, #%11 ; Установить режим SVC26
MSR CPSR_all, R0 ; Выполняем!
MOV R0, R0
\ Включите прерывания снова.
SWI "OS_IntOn"
ADR R0, выход
SWI "OS_Write0"
SWI "OS_NewLine"
\ Если Z установлено, выведите Z установлено, иначе выведите Z не установлено
ADR R0, zunset
ADREQ R0, zset
SWI "OS_Write0"
SWI "OS_NewLine"
\ Возврат в режим USR
BIC R14, PC, #3
TEQP R14, #0
MOV R0, R0
\ И уходим отсюда.
LDMFD R13!, {PC}
.zunset
EQUS "Флаг Z не установлен (это неправильно!)"
EQUB 0
ALIGN
.zset
EQUS " Флаг Z установлен (как и ожидалось!)"
EQUB 0
ALIGN
.entering
EQUS " Сейчас мы перейдем в 32-битный режим, скрестите пальцы!"
EQUB 0
ALIGN
]
NEXT
PRINT "Executing code"
CALL code%
PRINT "Finished"
END
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Программы на заказ
Отзывы
Контакты