ARM регистры


ARM предлагает шестнадцать регистров, от R0 до R15. Все регистры представляют собой 32-битные значения. Из этих регистров только два имеют конкретное назначение.

  • R15 - это программный счетчик.
  • R14 устанавливается в адрес возврата при выполнении инструкции BL.
Существуют различные соглашения, которые определяют другие специфические назначения регистров (например, R13 - указатель стека), однако сам ARM не предъявляет никаких требований к другим регистрам. Действительно, если вы сохраните (т.е. вытолкнете в стек) адрес возврата в R14, то сможете использовать его как регистр общего назначения.

Если вы пишете программы для пользовательского режима: это, плюс применимые соглашения, - почти все, что вам нужно знать.

Полный набор регистров

Однако на самом деле 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 и их распределение по режимам.

РегистрПользовательСистемаСупервизорПрерываниеНеопределённыйIRQFIQ
R0
R1
R2
R3
R4
R5
R6
R7
R8R8_fiq
R9R9_fiq
R10R10_fiq
R11R11_fiq
R12R12_fiq
R13R13_svcR13_abtR13_undR13_irqR13_fiq
R14R14_svcR14_abtR14_undR14_irqR14_fiqR15


Именование регистров APCS

Стандарт вызова процедур Arm определяет имена для различных регистров следующим образом:

РегистрНазвание в APCНазначение
R0a1Регистр аргументов, передача значений. Не требует сохранения между вызовами. Результаты функций обычно возвращаются в R0.
R1a2Переменные регистры, используются внутри функций. Если используются, должны сохраняться.
R2a3Лимит стека / дескриптор фрагмента стека.
R3a4Указатель фрейма (Frame Pointer). Содержит ноль или указывает на структуру стека для трассировки.
R4v1Временное рабочее пространство при входе в процедуру.
R5v2Указатель стека (Stack Pointer). Полностью нисходящий стек, указывает на нижнюю свободную ячейку.
R6v3Регистр связи (Link Register). Содержит адрес возврата при выходе из функции.
R7v4Счётчик команд (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)IRQFIQ
R0R0
R1R1
R2R2
R3R3
R4R4
R5R5
R6R6
R7R7
R8R8R8_fiq
R9R9R9_fiq
R10R10R10_fiq
R11R11R11_fiq
R12R12R12_fiq
R13R13R13_svcR13_irqR13_fiq
R14R14R14_svcR14_irqR14_fiq
R15PC + 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 - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегистатьи IT, процессоры, arm, ассемблер

Обсудить или задать вопрос по этой или любой другой теме можно на нашем форуме



Урок 46. Константы и перечисления C#
Почему MySQLi лучше MySQL?
Урок 1. Установка Laravel, php, миграции