Программы на языка ассемблера для компилятора GNU сохраняются в файле, имя которого оканчивается на .s
или .S
. Во втором случае (с заглавной буквой) подразумевается, что текст программы может быть обработан препроцессором.
Для компиляции используется одна из команд:
arm-linux-gnueabi-as
или arm-linux-gnueabi-gcc
. В первом случае текст только компилируется в объектный файл, во втором - в выполняемую программу, скомпонованную со стандартной библиотекой Си, из которой можно использовать функции ввода-вывода.
Процессоры ARM поддерживают два набора команд: основной 32-битный arm
, и уплотнённый 16-битный thumb
, между которыми процессор умеет переключаться. В рамках данного семинара мы будем использовать 32-битный набор инструкций, поэтму тексты нужно компилировать с опцией -marm
.
// Это комментарий, как в C++
.text // начало секции .text с кодом программы
.global f // указание о том, что метка f
// является доступной извне (аналог extern)
f: // метка (заканчивается двоеточием)
// последовательность команд
mul r0, r0, r3
mul r0, r0, r3
mul r1, r1, r3
add r0, r0, r1
add r0, r0, r2
mov r1, r0
bx lr
Процессор может выполнять операции только над регистрами - 32-биьными ячейками памяти в ядре процессора. У ARM есть
16 регистров, доступных программно: r0
, r1
, ... ,r15
.
У регистров r13
...r15
имеются специальные назначения и дополнительные имена:
r15
=pc
: Program Counter - указатель на текущую выполняемую инструкциюr14
=lr
: Link Register - хранит адрес возврата из функцииr13
=sp
: Stack Pointer - указатель на вершину стека.
Выполнение команд может приводить к появлению некоторой дополнительной информации, которая хранится в регистре флагов. Флаги относятся к последней выполненной команде. Основные флаги, это:
C
: Carry - возникло беззнаковое переполнениеV
: oVerflow - возникло знаковое переполнениеN
: Negative - отрицательный результатZ
: Zero - обнуление результата.
Полный перечень 32-битных команд см. в этом reference, начиная со 151 страницы.
Архитектура ARM-32 подразумевает, что почти команды могут иметь условное выполнение. Условие кодируется 4-мя битами в самой команде, а с точки зрения синтаксиса ассемблера у команд могут быть суффиксы.
Таким образом, каждая команда состоит из двух частей (без разделения пробелами): сама команда и её суффикс.
AND regd, rega, argb
// regd ← rega & argbEOR regd, rega, argb
// regd ← rega ^ argbSUB regd, rega, argb
// regd ← rega − argbRSB regd, rega, argb
// regd ← argb - regaADD regd, rega, argb
// regd ← rega + argbADC regd, rega, argb
// regd ← rega + argb + carrySBC regd, rega, argb
// regd ← rega − argb − !carryRSC regd, rega, argb
// regd ← argb − rega − !carryTST rega, argb
// set flags for rega & argbTEQ rega, argb
// set flags for rega ^ argbCMP rega, argb
// set flags for rega − argbCMN rega, argb
// set flags for rega + argbORR regd, rega, argb
// regd ← rega | argbMOV regd, arg
// regd ← argBIC regd, rega, argb
// regd ← rega & ~argbMVN regd, arg
// regd ← ~argb
EQ equal (Z)
NE not equal (!Z)
CS or HS carry set / unsigned higher or same (C)
CC or LO carry clear / unsigned lower (!C)
MI minus / negative (N)
PL plus / positive or zero (!N)
VS overflow set (V)
VC overflow clear (!V)
HI unsigned higher (C && !Z)
LS unsigned lower or same (!C || Z)
GE signed greater than or equal (N == V)
LT signed less than (N != V)
GT signed greater than (!Z && (N == V))
LE signed less than or equal (Z || (N != V))
Счетчик pc
автоматически увеличивается на 4 при выполнении
очередной инструкции. Для ветвления программ изпользуются команды:
B label
- переход на метку; используется внутри функций для ветвлений, связанных с циклами или условиямиBL label
- сохранение текущегоpc
вlr
и переход наlabel
; обычно используется для вызова функцийBX register
- переход к адресу, указанному в регистре; обычно используется для выхода из функций.
Процессор может выполнять операции только над регистрами. Для взаимодействия с памятью используются отдельные инструкции загрузки/сохранения регистров.
LDR regd, [regaddr]
- загружает машинное слово из памяти по адресу, хранящимся в regaddr, и сохраняет его в регистре regdSTR reds, [regaddr]
- сохраняет в памяти машинное слово из регистра regs по адресу, указанному в регистре regaddr.