Описание ARM
В данном руководстве приводятся сведения по ARM-процессорам, необходимые для понимания работы Малого Преобразователя Глагола, который производит ARM код, работающий под управлением PocketPC. В конце руководства приводится справочник по всем используемым командам.
Первый ARM-процессор (ARM – сокращение от Advanced RISC Machine) был спроектирован и изготовлен Acorn Computer Group в середине 80-х. В 1990 Acorn вместе с Apple Computer создали новую компанию под названием Advaced RISC Machines Ltd. В наши дни ARM Ltd не производит процессоров, а только проектирует их и продаёт разрешения на изготовление процессоров третьим производителям. XScale процессоры от Intel тоже разработаны на основе ARM. На текущий момент существует несколько версий архитектуры ARM-процессоров, которые, в основном, отличаются наборами команд в части плавающей и векторной арифметики. В данном руководстве рассматривается архитектура 4-го издания, набор команд которой поддерживается всеми современными ARM-процессорами. Плавающая и векторная арифметика в данном руководстве не рассматривается.
ARM – это 32-х разрядный процессор с RISC-архитектурой. RISC - сокращение от Reduced Instruction Set Computer – машина с сокращённым набором команд, ориентированная на быстрое выполнение относительно небольшого набора встроенных команд. ARM имеет архитектуру вида "загрузить/сохранить", где команды, обрабатывающие данные, могут работать только с регистрами, а не с памятью напрямую. Поддерживаются команды многократной загрузки и сохранения, а также условное выполнение всех команд. Каждая команда имеет одну и ту же длину – 32 разряда.
У ARM есть 16 видимых 32-х разрядных регистров: с R0 по R15. Для упрощения можно считать, что есть 13 регистров общего назначения – с R0 по R11, и четыре регистра, которым отведена особая роль в Глагол-приложениях:
R12 или FP – указатель окна
R13 или SP – указатель стека
R14 или LR – адрес возврата
R15 или PC – счётчик команд
Перед выполнением каждой команды R15 увеличивается на 4 (размер команды в байтах). Когда вызывается задача по команде BL (см. далее), то в R14 помещается адрес следующей за BL команды. Возврат из задачи осуществляется занесением данного значения обратно в программный счетчик R15.
При заполнении стека указатель SP обычно уменьшается и указывает на последнее, записанное в него слово. Например, после занесения последовательно в стек чисел 1, 2 и 3 память будет выглядеть следующим образом:
|
адрес | значение |
SP -> |
n-8 | 3 |
|
n-4 | 2 |
|
n | 1 |
Учтите, что для указателя окна FP в PocketPC (см. далее) обычно выделяется R11, а не R12.
Как было написано выше, в ARM, как и в большинстве других RISC, длина двоичного кода команды постоянная. Старшие четыре разряда команды всегда используются для задания кода условия КУ, при котором данная команда будет выполняться.
Интересующие нас команды можно разделить на три группы: команды обработки данных, команды загрузки/сохранения и команды переходов.
Для лучшего понимания возможностей команд будем также рассматривать и их двоичный код.
Команды обработки данных в общем случае имеют следующий вид:
<команда> <регистр назначения>, <1-е данное>, <2-е данное>
<регистр назначения> – регистр (R0-R15), в который записывается результат выполненной команды, <1-е данное> также может быть одним из 15 регистров, а <2-е данное> может быть регистром, смещенным регистром или непосредственным значением. Таким способом задаются команды сложения, вычитания, пересылки и логические команды.
Примеры:
сложение |
ADD R1,R1,#10 |
R1:=R1+10 |
вычитание |
SUB R1,R1,#0 x10 |
R1:=R1-16 |
логическое И |
AND R0,R1,R2 |
R0:=R1 AND R2 |
логическое искл. ИЛИ |
EOR R0,R1,#10 |
R0:=R1 XOR 10 |
логическое ИЛИ |
ORR R0,R1,R2 |
R0:=R1 OR R2 |
пересылка |
MOV R2,R0 |
R2:=R0 |
Заметьте, что в записи команд перед числами всегда ставится "#", а шестнадцатеричные числа начинаются с "0x".
В двоичном коде команд присутствуют: код условия выполнения команды КУ, код производимого действия КД, регистр назначения Rd, регистр первого данного Rn и регистр Rm или постоянная для второго данного. Необычная, но полезная особенность – разряды второго данного перед выполнением заданного действия могут быть передвинуты на любое место 32-х разрядного слова.
РРРР |
РРР |
РРРРР |
РРРР |
РРРР |
РРРРР |
РР |
Р |
РРРР |
4 |
3 |
5 |
4 |
4 |
5 |
2 |
1 |
4 |
КУ |
000 |
КД |
Rn |
Rd |
k |
сс |
0 |
Rm |
ADD Rd, Rn, Rm, LSL k ; Rd:=Rn+(Rm LSL k)
РРРР |
РРР |
РРРРР |
РРРР |
РРРР |
РРРР |
Р |
РР |
Р |
РРРР |
4 |
3 |
5 |
4 |
4 |
4 |
1 |
2 |
1 |
4 |
КУ |
000 |
КД |
Rn |
Rd |
Rs |
0 |
сс |
1 |
Rm |
SUB Rd, Rn, Rm, LSR Rs ; Rd:=Rn-(Rm LSR Rs)
При этом способ сдвига разрядов (сс) может быть задан как:
LSL – логический сдвиг влево
ASL – арифметический сдвиг влево
LSR – логический сдвиг вправо
ASR – арифметический сдвиг вправо
ROR – вращение вправо
RRX – однократное вращение вправо с флагом переноса.
Одной из причуд ARM является то, что для непосредственного числового значения выделяется область только из 8 разрядов. Это очень неприятное ограничение, и досадно, что при этом в каждой команде тратится 4 разряда на код условия КУ выполнения команды, хотя эта возможность обычно используется только в командах условного перехода. И для сдвига этого 8-ми разрядного числа можно использовать только правое вращение на чётное число разрядов.
РРРР |
РРР |
РРРРР |
РРРР |
РРРР |
РРРР |
РРРРРРРР |
4 |
3 |
5 |
4 |
4 |
4 |
8 |
КУ |
000 |
КД |
Rm |
Rd |
k |
число8пв |
ORR Rd, Rm, число8пв ROR 2*k ; Rd:= Rm OR (число8пв ROR (2* k)) MOV Rd, число8пв ROR 2*k ; Rd:=число8пв ROR (2*k)
Загрузить в регистр Rd значение из памяти:
LDR Rd, <адрес>
Пример: LDR R0,[R1] загружает в R0 32-х разрядное слово из памяти с адресом, хранящимся в R1. Также существуют команды, ответственные за загрузку 8 и 16 разрядных данных и соответствующие команды, сохраняющие содержимое регистров в памяти.
Сохранить значение регистра Rd в памяти:
STR Rd, <адрес>
Сохранить младшие 8 разрядов регистра Rd в памяти:
STRB Rd, <адрес>
ARM также поддерживает сохранение/загрузку нескольких регистров – команда STM (сохранить несколько регистров в памяти):
STM<ИРО> Rd{!}, <список регистров>
Где ИРО – изменение регистра основы, см. последующие примеры. Регистр основы Rd содержит начальный адрес памяти, куда будет производиться запись значений регистров, перечисленных в списке команды. Регистр основы может быть любым регистром, но обычно используется указатель стека SP. Например:
STMDB SP!, {R0-R3,R6}
сохраняет последовательно регистры R6, R3, R2, R1 и R0 в стеке, уменьшая перед каждой пересылкой регистр основы SP на 4 байта (<ИРО> = DB – сокращение от Decrement Befor e). Очевидно, что после выполнения данной команды регистр основы (указатель стека) будет указывать туда, где сохранён регистр R0. Знак "!" после SP обозначает то, что регистр основы будет обновляться после каждого переноса данных. Если бы этого знака не было, то после выполнения команды оказалось бы, что SP остался прежним, а все регистры последовательно сохранялись бы в одну и ту же ячейку по адресу SP-4.
Команда LDM служит для одновременной загрузки нескольких регистров из памяти. Пример:
LDMIA SP!, {R0-R3,R6}
восстанавливает последовательно регистры R0, R1, R2, R3 и R6 из стека, увеличивая после каждой пересылки регистр основы SP на 4 байта (<ИРО> = IA – сокращение от Increment After).
Есть некоторые неудобства в командах загрузки и сохранения в память. Адрес в этих командах вычисляется или как сумма значений двух регистров (значение одного из этих регистров предварительно может быть сдвинуто), или как сумма регистра и смещения. А для области смещения отведено всего лишь 12 разрядов. Было бы гораздо лучше для этих целей иметь 16 разрядов. Вместо этого существует богатое разнообразие способов вычисления и сохранения адресов доступа:
РРРР |
РРР |
РРРРР |
РРРР |
РРРР |
РРРРРРРРРРРР |
4 |
3 |
5 |
4 |
4 |
12 |
КУ |
01 0 |
КД |
Rn |
Rd |
смещение12 |
LDR Rd, [Rn,#-смещение12] ; Rd:=[Rn-смещение12] LDR Rd, [Rn,#+смещение12]! ; адр:=Rn+смещение12, Rd:=[адр], Rn:=адр LDR Rd, [Rn],#-смещение12 ; Rd:=[Rn], Rn:=[Rn-смещение12]
РРРР |
РРР |
РРРРР |
РРРР |
РРРР |
РРРРР |
РР |
Р |
РРРР |
4 |
3 |
5 |
4 |
4 |
5 |
2 |
1 |
4 |
КУ |
011 |
КД |
Rn |
Rd |
k |
сс |
0 |
Rm |
LDR Rd, [Rn,-Rm,LSL k] ; Rd:=[Rn+((-Rm) LSL k)] STR Rd, [Rn,Rm,LSR k] ; [Rn+(Rm LSR k)]:=Rd STR Rd, [Rn,-Rm,ROR k]! ; адр:=Rn+((-Rm) ROR k), [адр]:=Rd, Rn:=адр STR Rd, [Rn],Rm,ASR k ; [Rn]:=Rd, Rn:=Rn+(Rm ASR k)
РРРР |
РРР |
РРРРР |
РРРР |
РРРРРРРРРРРРРРРР |
4 |
3 |
5 |
4 |
16 |
КУ |
011 |
КД |
Rn |
{регистры} |
LDMDB Rn, {регистры} ; Повторять: Ri:=[ Rn-4] LDMDA Rn!, {регистры} ; Повторять: Ri:=[ Rn], Rn:=Rn-4 STMIB Rn, {регистры} ; Повторять: [Rn+4]:= Ri STMIA Rn!, {регистры} ; Повторять: [Rn+4]:= Ri, Rn:=Rn+4 STMDB Rn!, {регистры} ; Повторять: Rn:= Rn-4, [Rn]:=Ri
Есть две такие команды:
переход:
B <адрес>
и переход с возвратом:
BL <адрес>
После выполнения этих команд значение счётчика команд PC увеличится на <адрес>- PC байт. И, как было упомянуто выше, после выполнения перехода с возвратом дополнительно в LR будет занесён адрес следующей команды.
Командам переходов предоставлена область для смещения (слов) в 24 разряда, что позволяет совершать относительные переходы на +-32Мб.
РРРР |
РРР |
Р |
РРРРРРРРРРРРРРРРРРРРРРРР |
4 |
3 |
1 |
24 |
КУ |
101 |
L |
смещение24 |
B смещение24*4 ; R15:=R15+смещение24*4 BL смещение24*4 ; R14:=R15, R15:=R15+смещение24*4
Так как все команды на ARM занимают всего лишь 32 бита, включая код действия, код условия выполнения и код данных, то нет никакого способа за одну команду непосредственно заслать в регистр большое значение. Эту трудность можно преодолеть с помощью сдвигов.
Например, чтобы заслать в R0 шестнадцатеричное число 0x2008, нам нужно выполнить следующие команды:
MOV R0, #8 ; R0:=8 ADD R0, R0, R0,LSL #10 ; R0:=8+(0x8 LSL 10)
Эту же засылку можно сделать, используя неявный сдвиг:
MOV R0, #0x2000 ; R0:=0x2 ROR (10*2) ADD R0, R0, #8 ; R0:=0x2000+8
В крайнем случае, можно загрузить постоянную и из памяти:
LDR R0, |пост| ; R0:=[пост] B |пост|+4 ; Переход через слово данных |пост| DCD 0 x2008 ; пост=0x2008
Или то же самое без метки |пост|:
LDR R0, [PC] B .+8 DCD 0x2008
В последнем примере "." обозначает (для преобразователя кода) адрес текущей команды, а DCD ( Define constant data) - заполнение памяти (4 байта) данным числом.
Предположим, что нам нужно сконструировать код, который будет повторяться 3 раза подряд. Обычно это делается так:
MOV R0, #3 ; счётчик повторов |кольцо| ... SUB R0, R0, #1 ; R0:=R0-1 CMP R0, #0 ; проверяем, R0=0 BNE |кольцо| ; если Z-флаг!=1, то переход к метке кольцо
Этот код можно улучшить, используя команду SUB с суффиксом S, при использовании которого выставляются все флаги, в т.ч. и Z-флаг.
MOV R0, #3 |кольцо| ... SUBS R0, R0, #1 BNE |кольцо|
Следующая таблица показывает роль регистров при вызове задач ОС:
Регистр |
Синоним |
Назначение |
Использование |
R0-R3 |
|
1-4 слово приёмников |
временный |
R4-R10 |
|
|
охраняемый |
R11 |
FP |
указатель окна |
охраняемый |
R12 |
IP |
начальный SP |
временный |
R13 |
SP |
указатель стека |
охраняемый |
R14 |
LR |
адрес возврата |
охраняемый |
R15 |
PC |
счётчик команд |
|
Ответ задачи возвращается через R0.
Регистры R0-R3 содержат первые 4 слова приёмников задачи. Оставшиеся слова при необходимости размещаются в стеке. Охраняемые регистры задача должна оставить неизменными после окончания своей работы.
Стек задачи создаётся в прологе, а оканчивает работу в эпилоге. Он строится из области сохранённых регистров – ОСР, и собственной области задачи – СОЗ. ОСР содержит значения тех охраняемых регистров, которые задача может затереть при своей работе. А СОЗ - это память для собственных переменных задачи. Для ссылки на ОСР и СОЗ обычно используется указатель окна FP.
Если задаче требуются регистры R0-R4, или если ей требуется адрес приёмника, который хранится в R0-R4, то в прологе задача может сохранить данные регистры в ОСР.
Если задача не сохраняет охраняемые регистры, не выделяет память для своих переменных и память под источники вызываемых задач, то ей не нужен указатель окна FP.
Если задача использует указатель окна FP, то она не имеет права его изменять между прологом и эпилогом. А задачи без указателя окна FP не имеют права изменять указатель стека SP.
Значение указателя стека SP никогда не должно превышать адреса ОСР. Это предохраняет сохранённые значения от затирания при внешних прерываниях, которые могут произойти при работе пролога или эпилога.
Указатель окна FP и указатель стека SP всегда необходимо выравнивать по границе слова.
Пролог состоит из трёх неразрывных частей:
1. Копирование указателя стека SP в R12. Далее R12 будет использоваться для вычисления указателя окна FP.
2. При необходимости сохранение в СОЗ приёмников из R0-R4 и охраняемых регистров с одновременной настройкой указателя стека SP на новую вершину.
3. Захват памяти для собственных переменных задачи посредством вычитания из SP размера переменных (выровненного на границу слова). Если размер не помещается в одну инструкцию, то для его временного хранения используется регистр FP.
Пример пролога с окном.
MOV R12, SP ; 1 часть STMDB SP!, {R0-R3} ; 2 часть STMDB SP!, {R4-R12, LR} ; 2 часть SUB FP, R12, #16 ; 3 часть: 16 байт для переменных задачи
Пример пролога без окна.
MOV R12, SP ; 1 часть STMDB SP!, {R0-R3} ; 2 часть STMDB SP!, {R4-R12, LR} ; 2 часть
Пример пролога без окна и использования R12.
STMDB SP!, {...,LR} ; 1 и 2 часть
Эпилог предназначен для восстановления охраняемых регистров.
Если использовалось окно, то в качестве регистра основы при восстановлении всех регистров (включая PC и SP) необходимо использовать указатель окна FP, а не указатель стека SP.
Пример эпилога с окном:
LDMIA FP!, {R4-FP, SP, PC}
Пример эпилога без окна:
LDMIA SP!, {R4-FP, SP, PC}
Rd |
регистр назначения |
Rn |
регистр основания, регистр 1-го данного |
Rm |
регистр данного |
Rs |
регистр сдвигов, регистр множителя |
{КУ} |
если присутствует, то команда будет выполняться только при состоянии процессора, которое соответствует заданному условию, см. Коды условий |
{S} |
если присутствует, то флаги условий будут обновлены в соответствии с ответом |
{!} |
если присутствует, то регистр основы Rn будет обновлён после переноса данных |
<Г2Д> |
см. Гибкое 2-е данное |
<реги> |
список разделённых запятыми регистров, заключённый в фигурные скобки |
<число N> |
N разрядное число |
<АСББ> |
см. Адресация слов и беззнаковых байт |
<АПЗБ> |
см. Адресация полуслов и знаковых байт |
<ИРО> |
см. Изменение регистра основы |
+/- |
+ или - (+ может быть опущен) |
Действие |
Код |
Флаги c S |
Поведение |
Сложение |
ADD{КУ}{S} Rd,Rn,<Г2Д> |
N Z C V |
Rd:=Rn+Г2Д |
с переносом |
ADC{КУ}{S} Rd,Rn,<Г2Д> |
N Z C V |
Rd:=Rn+Г2Д+Перенос |
Вычитание |
SUB{КУ}{S} Rd,Rn,<Г2Д> |
N Z C V |
Rd:=Rn-Г2Д |
с переносом |
SBC{КУ}{S} Rd,Rn,<Г2Д> |
N Z C V |
Rd:=Rn-Г2Д-NOT(Перенос) |
обратное |
RSB{КУ}{S} Rd,Rn,<Г2Д> |
N Z C V |
Rd:=Г2Д-Rn |
обратное с переносом |
RSC{КУ}{S} Rd,Rn,<Г2Д> |
N Z C V |
Rd:=Г2Д-Rn-NOT(Перенос) |
Умножение |
MUL{КУ}{S} Rd,Rm,Rs |
N Z |
Rd:=(Rm*Rs)[31:0] |
с накоплением |
MLA{КУ}{S} Rd,Rm,Rs,Rn |
N Z |
Rd:=((Rm*Rs)+Rn)[31:0] |
широкое |
SMULL{КУ}{S} RdМл,RdСт,Rm,Rs |
N Z |
RdСт,RdМл:=Rm*Rs |
широкое с накоплением |
SMLAL{КУ}{S} RdМл,RdСт,Rm,Rs |
N Z |
RdСт,RdМл:=RdСт,RdМл+Rm*Rs |
широкое беззнаковое |
UMULL{КУ}{S} RdМл,RdСт,Rm,Rs |
N Z |
RdСт,RdМл:=БезЗн(Rm*Rs) |
широкое беззнаковое с накоплением |
UMLAL{КУ}{S} RdМл,RdСт,Rm,Rs |
N Z |
RdСт,RdМл:=БезЗн(RdСт,RdМл+Rm*Rs) |
Действие |
Код |
Флаги c S |
Поведение |
Пересылка |
MOV{КУ}{S} Rd,<Г2Д> |
N Z C |
Rd:=Г2Д |
отрицательная |
MVN{КУ}{S} Rd,<Г2Д> |
N Z C |
Rd:=0 FFFFFFFFH EOR Г2Д |
И |
AND{КУ}{S} Rd,Rn,<Г2Д> |
N Z C |
Rd:=Rn AND Г2Д |
Искл. ИЛИ |
EOR{КУ}{S} Rd,Rn,<Г2Д> |
N Z C |
Rd:=Rn EOR Г2Д |
ИЛИ |
ORR{КУ}{S} Rd,Rn,<Г2Д> |
N Z C |
Rd:=Rn OR Г2Д |
Проба |
TST{КУ} Rn,<Г2Д> |
N Z C |
Обновить флаги для (Rn AND Г2Д) |
Проба на равенство |
TEQ{КУ} Rn,<Г2Д> |
N Z C |
Обновить флаги для (Rn EOR Г2Д) |
Сравнение |
CMP{КУ}{S} Rn,<Г2Д> |
N Z C V |
Обновить флаги для (Rn-Г2Д) |
отрицательное |
CMN{КУ}{S} Rn,<Г2Д> |
N Z C V |
Обновить флаги для (Rn+Г2Д) |
Очистка разрядов |
BIC{КУ}{S} Rd,Rn,<Г2Д> |
N Z C |
Rd:=Rn AND NOT Г2Д |
Действие |
Код |
Поведение |
Примечание |
Загрузка слова |
LDR{КУ} Rd,<АСББ> |
Rd:=[адрес] |
Rd не м.б. R15 |
Загрузка PC |
LDR{КУ} R15,<АСББ> |
R15:=[адрес][31:1] |
|
Загрузка байта |
LDR{КУ}B Rd,<АСББ> |
Rd:=РасшНулём [адрес] [7:0] |
Rd не м.б. R15 |
знаковая |
LDR{КУ}SB Rd,<АПЗБ> |
Rd:=РасшЗнаком [адрес] [7:0] |
Rd не м.б. R15 |
Загрузка полслова |
LDR{КУ}H Rd,<АПЗБ> |
Rd:=РасшНулём [адрес] [15:0] |
Rd не м.б. R15 |
знаковая |
LDR{КУ}SH Rd,<АПЗБ> |
Rd:=РасшЗнаком [адрес] [15:0] |
Rd не м.б. R15 |
Загрузка составная |
LDM{КУ}<ИРО> Rn{!},<реги> |
Загрузить в регистры значения из [Rn] |
в R15 только [31:1] |
Сохранение слова |
STR{КУ} Rd,<АСББ> |
[адрес]:=Rd |
|
Сохранение байта |
STR{КУ}B Rd,<АСББ> |
[адрес ][7:0]:=Rd[7:0] |
|
Сохранение полслова |
STR{КУ}H Rd,<АПЗБ> |
[адрес ][15:0]:=Rd[15:0] |
|
Сохранение составное |
STM{КУ}<ИРО> Rn{!},<реги> |
Сохранить значения регистров в [Rn] |
|
Обмен словами |
SWP{КУ} Rd,Rm,[Rn] |
вр:=[Rn], [Rn]:=Rm, Rd:=вр |
|
Обмен байтами |
SWP{КУ}B Rd,Rm,[Rn] |
вр:=РасшНулём[Rn][7:0], [Rn][7:0]:=Rm[7:0], Rd:=вр |
|
Действие |
Код |
Поведение |
Примечание |
Переход |
B{КУ} метка |
R15 :=метка |
Метка в пределах +-32Мб от тек. команды |
с возвратом |
BL{КУ} метка |
R15:=метка, |
Метка в пределах +-32Мб от тек. команды |
Код |
Значение |
Примечание |
#<число8пв> |
32-разрядное число, полученное вращением 8-разрядного числа на чётное число разрядов вправо |
Пример: #0x10000000, т.к. 0 x10000000=0x10 ROR (4*2) |
Rm, LSL #<сдвиг> |
непосредственный логический сдвиг Rm влево |
Разрешен сдвиг на 0-31 разрядов |
Rm, LSR #<сдвиг> |
непосредственный логический сдвиг Rm вправо |
Разрешен сдвиг на 1-32 разрядов |
Rm, ASR #<сдвиг> |
непосредственный арифметический сдвиг Rm вправо |
Разрешен сдвиг на 1-32 разрядов |
Rm, ROR #<сдвиг> |
непосредственное вращение Rm вправо |
Разрешен сдвиг на 1-31 разрядов |
Rm |
Rm |
|
Rm, RRX |
однократное вращение вправо Rm с флагом переноса |
|
Rm, LSL Rs |
логический сдвиг Rm влево на Rs разрядов |
|
Rm, LSR Rs |
логический сдвиг Rm вправо на Rs разрядов |
|
Rm, ASR Rs |
арифметический сдвиг Rm вправо на Rs разрядов |
|
Rm, ROR Rs |
вращение Rm вправо на Rs разрядов |
|
Вычисления адреса |
Смещение |
Код |
Примечание |
До доступа |
Непосредственное |
[Rn, #+/-<число12>]{!} |
|
Без смещения |
[Rn] |
Равнозначно [Rn,#0] |
|
Регистровое |
[Rn, +/-Rm]{!} |
|
|
Взвеш. регистровое |
[Rn, +/-Rm, LSL #<сдвиг>]{!} |
Разрешен сдвиг на 0-31 разрядов |
|
[Rn, +/-Rm, LSR #<сдвиг>]{!} |
Разрешен сдвиг на 1-32 разрядов |
||
[Rn, +/-Rm, ASR #<сдвиг>]{!} |
Разрешен сдвиг на 1-32 разрядов |
||
[Rn, +/-Rm, ROR #<сдвиг>]{!} |
Разрешен сдвиг на 1-31 разрядов |
||
[Rn, +/-Rm, RRX]{!} |
|
||
После доступа |
Непосредственное |
[Rn], #+/-<число12> |
|
Регистровое |
[Rn], +/-Rm |
|
|
Взвеш. регистровое |
[Rn], +/-Rm, LSL #<сдвиг> |
Разрешен сдвиг на 0-31 разрядов |
|
[Rn], +/-Rm, LSR #<сдвиг> |
Разрешен сдвиг на 1-32 разрядов |
||
[Rn], +/-Rm, ASR #<сдвиг> |
Разрешен сдвиг на 1-32 разрядов |
||
[Rn], +/-Rm, ROR #<сдвиг> |
Разрешен сдвиг на 1-31 разрядов |
||
[Rn], +/-Rm, RRX |
|
Вычисления адреса |
Смещение |
Код |
Примечание |
До доступа |
Непосредственное |
[Rn, #+/-<число8>]{!} |
|
Без смещения |
[Rn] |
Равнозначно [Rn,#0] |
|
Регистровое |
[Rn, +/-Rm]{!} |
|
|
После доступа |
Непосредственное |
[Rn], #+/-<число8> |
|
Регистровое |
[Rn], +/-Rm |
|
Код |
Сокращение от |
Регистр основы |
IA |
Increment After |
увеличивать после |
IB |
Increment Befor |
увеличивать до |
DA |
Decrement After |
уменьшать после |
DB |
Decrement Befor |
уменьшать до |
Код |
Сокращение от |
Условие |
EQ |
Equal |
равно |
NE |
Not equal |
не равно |
CS/HS |
Carry Set / Unsigned higher or same |
есть перенос / старше или такое же |
CC/LO |
Carry Clear / Unsigned lower |
нет переноса / младше |
MI |
Minus |
отрицательно |
PL |
Plus |
положительно или 0 |
VS |
Overflow |
переполнено |
VC |
No overflow |
не переполнено |
HI |
Unsigned higher |
старше |
LS |
Unsigned lower or same |
младше или такое же |
GE |
Signed greater than or equal |
больше или равно |
LT |
Signed less than |
меньше |
GT |
Signed greater than |
больше |
LE |
Signed less than or equal |
меньше или равно |
AL |
Always |
всегда (обычно опускается) |
|