Операторы ассемблера
В этой главе описываются операторы ассемблера, составляющие программу на языке ассемблера.
Это - общий формат оператора ассемблера:
[ label_field ] [ opcode_field [ operand_field ] ] [ comment_field ] |
Каждое из изображенных полей описано подробно в одном из следующих разделов.
Строка может содержать многократные операторы, разделенные @
символ для ассемблера PowerPC (и точка с запятой для i386 ассемблера), который может тогда сопровождаться единственным комментарием, которому предшествует точка с запятой для ассемблера PowerPC (и a #
символ для i386 ассемблера):
[ statement [ @ statement ...] ] [ ; comment_field ] |
Соблюдающие правила применяются к использованию пробела в операторе:
Пробелы или вкладки используются для разделения полей.
По крайней мере одно пространство или вкладка должны произойти между полем кода операции и полем операнда.
Пробелы могут появиться в поле операнда.
Пробелы и вкладки являются значительными, когда они появляются в символьной строке.
Поле метки
Метки являются идентификаторами, которые Вы используете для тегирования расположений программы и объектов данных. Каждая метка составлена из идентификатора и завершающегося двоеточия. Формат поля метки:
identifier: [ identifier: ] ... |
Дополнительное поле метки может произойти только в начале оператора. Следующий пример показывает поле метки, содержащее две метки, сопровождаемые (стиль PowerPC) комментарий:
var: VAR: ; two labels defined here |
Как показано здесь, буквы в идентификаторах чувствительны к регистру, и могут использоваться и прописные и строчные буквы.
Поле кода операции
Поле кода операции оператора ассемблера идентифицирует оператор как машинную команду, ассемблерную директиву или макрос, определенный программистом:
Машинная команда обозначена мнемоникой команды. Оператор ассемблера, содержащий мнемонику команды, предназначается для создания единственной исполнимой машинной команды. Работа и использование каждой инструкции описаны в руководстве пользователя производителя.
Ассемблерная директива (или pseudo-op) выполняет некоторую функцию во время сборочного процесса. Это не производит исполняемого кода, но это может присвоить пространство для данных в программе.
Макросы определяются с помощью
.macro
директива (см. .macro, .endmacro, .macros_on, и .macros_off для получения дополнительной информации).
Одни или более пробелов или вкладки должны разделить поле кода операции от следующего поля операнда в операторе. Пробелы или вкладки являются дополнительными между меткой и полями кода операции, но они помогают улучшить удобочитаемость программы.
Intel i386 Архитектурно-зависимые Протесты
инструкции i386 могут воздействовать на байт, слово или данные длинного слова (последнее вызывает «двойным словом» Intel). Желаемый размер обозначен как часть мнемоники команды путем добавления запаздывания
b
,w
, илиl
:Мнемосхема
Описание
b
Байт (8-разрядные) данные.
w
Word (16-разрядные) данные.
l
Длинное слово (32-разрядные) данные.
Например, a
movb
инструкция перемещает байт данных, но amovw
инструкция перемещает 16-разрядное слово данных.Если никакой размер не указан, ассемблер пытается определить размер от операндов. Например, если 16-разрядные имена для регистров используются в качестве операндов, 16-разрядная работа выполняется. Когда и спецификатор размера и специфичное для размера имя регистра даны, спецификатор размера используется. Таким образом, следующее все корректны и результат в той же работе:
movw %bx,%cx
mov %bx,%cx
movw %ebx,%ecx
i386 код операции может также содержать дополнительные префиксы, разделяющиеся от кода операции наклонной чертой (
/
) символ. Префиксная мнемоника:Префикс
Описание
data16
Работа использует 16-разрядные данные.
addr16
Работа использует 16-разрядные адреса.
lock
Монопольная блокировка памяти.
wait
Ожидайте незаконченных числовых исключений.
cs
,ds
,es
,fs
,gs
,ss
Переопределение сегментного регистра.
rep
,repe
,repne
Повторите префиксы для команд работы со строковыми данными.
Больше чем один префикс может быть указан для некоторых кодов операций. Например:
lock/fs/xchgl %ebx,4(%ebp)
Переопределения сегментного регистра и 16-разрядные спецификации данных обычно даются как часть самого кода операции или его операндов. Например, следующие две строки блока генерируют те же инструкции:
movw %bx,%fs:4(%ebp)
data16/fs/movl %bx,4(%ebp)
Не все префиксы позволяются со всеми инструкциями. Ассемблер действительно проверяет, что повторные префиксы для строковых инструкций используются правильно, но иначе не проверяет на корректное использование.
Поле операнда
Поле операнда оператора ассемблера предоставляет параметры машинной команде, ассемблерной директиве или макросу.
Поле операнда может содержать один или несколько операндов, в зависимости от требований предыдущей машинной команды или ассемблерной директивы. Некоторые машинные команды и ассемблерные директивы не берут операнда, и некоторые берут два или больше. Если поле операнда содержит больше чем один операнд, операнды обычно разделяются запятыми, как показано здесь:
[ operand [ , operand ] ... ] |
Следующие типы объектов могут быть операндами:
Операнды регистра
Пары регистра
Операнды адреса
Строковые константы
Константы с плавающей точкой
Списки регистра
Выражения
Операнды регистра в машинной команде относятся к регистрам машины процессора или сопроцессора. Имена регистра могут появиться в смешанном случае.
Intel 386 архитектурно-зависимые протесты
Ассемблер OS X упорядочивает поля операнда для i386 инструкций в обратном порядке из соглашений Intel. Соглашение Intel является местом назначения сначала, второй источник; соглашение ассемблера OS X является источником сначала, целевая секунда. Где документация Intel описала бы Сравнивание и инструкцию Exchange для 32-разрядных операндов следующим образом:
CMPXCHG r/m32,r32 # Intel processor manual convention |
Синтаксис ассемблера OS X для этой той же инструкции:
cmpxchg r32,r/m32 # OS X assembler syntax |
Так, пример фактического ассемблерного кода для ассемблера OS X был бы:
cmpxchg %ebx,(%eax) # OS X assembly code |
Поле комментария
Ассемблер распознает два типа комментариев в исходном коде:
Строка, первый непробельный символ которой является символом хеша (
#
) комментарий. Этот стиль комментария полезен для передачи C вывод препроцессора через ассемблер. Обратите внимание на то, что комментарии формы:# line_number file_name level
в превратитесь:
.line line_number; .file file_name
Это может вызвать проблемы, когда комментарии этой формы, не предназначающиеся для указания номеров строки, предшествуют сборочным ошибкам, так как об ошибке сообщают как происходящий на строке относительно указанного в комментарии. Предположим, что программа содержит эти две строки сборочного источника:
# 500
.var
Если
.var
не был определен, этот фрагмент результаты в следующем сообщении об ошибке:var.s:500:Unknown pseudo-op: .var
Поле комментария, появляющееся на строке после одного или более операторов. Поле комментария состоит из надлежащего символа комментария и всех символов, следующих за ним на строке:
Символ
Описание
;
Символ комментария для процессоров PowerPC
#
Символ комментария для i386 процессоров архитектуры
Исходная строка ассемблера может состоять из просто поля комментария; в этом случае это эквивалентно использованию стиля комментария символа хеша:
# This is a comment.
; This is a comment.
Отметьте предупреждение, данное выше для комментариев символа хеша, начинающихся с числа.
Прямые операторы присваивания
В этом разделе описываются прямые операторы присваивания, не соответствующие нормальному синтаксису оператора, описанному ранее в этой главе. Прямой оператор присваивания может использоваться для присвоения значения выражения к идентификатору. Формат прямого оператора присваивания:
identifier = expression |
Если выражение в прямом присвоении является абсолютным, идентификатор является также абсолютным, и это может быть обработано как константа в последующих выражениях. Если выражение перемещаемо, идентификатор также перемещаем, и это считается заявленным в том же разделе программы как выражение.
Использование оператора присваивания походит на использование .set
директива (описанный в .set), за исключением того, что .set
директива делает значение выражения абсолютным. Это используется, когда постоянное время сборки требуется для того, что иначе генерировало бы переместимое выражение с помощью позиции независимое выражение symbol1 - symbol2
. Например, размер функции необходим как одно из полей информации об исключении C++ и установлен с:
.set L_foo_size, L_foo_end - _foo |
.long L_foo_size ; size of function _foo |
где позиция независимый указатель на функцию является другим полем информации об исключении C++ и установлен с:
.long _foo - . ; position independent pointer to _foo |
где время выполнения добавляет адрес указателя на его содержание для получения указателя на функцию.
Как только идентификатор был определен прямым оператором присваивания, он может быть переопределен — его значение является тогда результатом последнего оператора присваивания. Существует несколько ограничений, однако, относительно переопределения идентификаторов:
Идентификаторы регистра не могут быть переопределены.
Идентификатор, уже использовавшийся в качестве метки, не должен быть переопределен, так как это составило бы переопределение адреса места в программе. Кроме того, идентификатор, определенный в прямом операторе присваивания, не может позже использоваться в качестве метки. Только вторая ситуация производит ассемблерное сообщение об ошибке.