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 - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.
Читайте также:
Обсудить или задать вопрос по этой или любой другой теме можно на нашем форуме