Глава 2. Язык NASM

Содержание

2.1. Обзор ассемблерной строки NASM
2.2. Псевдо-инструкции
2.2.1. DB и ее друзья: Объявление инициализированных данных
2.2.2. RESB и ее друзья: Объявление неинициализированных данных
2.2.3. INCBIN: Включение внешних бинарных файлов
2.2.4. EQU: Определение констант
2.2.5. TIMES: Повторение инструкций или данных
2.3. Effective Addresses
2.3.1. 64-bit Displacements
2.3.2. RIP Relative Addressing
2.4. Immediate Operands
2.5. Constants
2.5.1. Numeric Constants
2.5.2. Character Constants
2.5.3. String Constants
2.5.4. Floating-Point Constants
2.6. Expressions
2.6.1. |: Bitwise OR Operator
2.6.2. ^: Bitwise XOR Operator
2.6.3. &: Bitwise AND Operator
2.6.4. << and >>: Bit Shift Operators
2.6.5. + and -: Addition and Subtraction Operators
2.6.6. *, /, //, % and %%: Multiplication and Division
2.6.7. Unary Operators: +, -, ~ and SEG
2.6.8. SEG and WRT
2.7. STRICT: Inhibiting Optimization
2.8. Critical Expressions
2.9. Local Labels

2.1. Обзор ассемблерной строки NASM

Как большинство ассемблеров, каждая исходная строка NASM содержит (если это не макрос, препроцессорная или ассемблерная директива: см. Глава 4), некоторую комбинацию четырех полей

метка:  инструкция операнды         ; комментарий

Как обычно, большинство этих полей необязательны; допускается присутствие или отсутствие любой комбинации метки, инструкции и комментарий. Конечно, необходимость поля операндов определяется присутствием и природой поля инструкций.

В NASM используется наклонная черта влево (\) как символ продолжения строки; если строка заканчивается наклонной чертой влево, то следующая будет рассматриватся как часть строки законченной наклонной чертой влево.

NASM не накладывает ограничений на количество пробелов в строке: метки могут иметь пробелы вначале, а инструкции могут не иметь никаких пробелов и т.п. Двоеточие после метки также необязательно (Это означает, что если вы хотите поместить в строку инструкцию lodsb, а введете lodab, строка останется корректной, но вместо инструкции будет объявлена метка. Выявить данные опечатки отчасти можно, введя в строке запуска NASM ключ -w+orphan-labels — в этом случае при обнаружении метки без заключительного двоеточия будет выдаваться предупреждение).

Допустимыми символами в метках являются буквы, цифры, знаки _, $, #, @, ~, . и ?. Допустимые символы в начале метки (первый символ метки) — только буквы, точка (.) (со специальным значением: см. Раздел 2.9), знак подчеркивания (_) и вопросительный знак (?). В идентификаторе может также присутствовать префикс $ для указания того, что это действительно идентификатор, а не зарезервированное слово; таким образом, если некоторый компонуемый вами модуль описывает символ eax, вы можете в коде NASM (для указания того, что это не регистр) сослаться на него так: $eax.

Поле инструкций может содержать любые процессорные инструкции: поддерживаются инструкции Pentium и P6, FPU, MMX, а также некоторые недокументированные инструкции. Перед инструкциями могут присутствовать префиксы LOCK, REP, REPE/REPZ или REPNE/REPNZ, используемые по их обычному предназначению. Поддерживаются префиксы размера адреса и операнда A16, A32, O16 и O32. В качестве префикса инструкции вы можете использовать также обозначение сегментного регистра: код es mov [bx],ax эквивалентен коду mov [es:bx],ax. Мы рекомендуем использовать последний синтаксис, т.к. он согласуется с другими синтаксическими особенностями языка, однако для инструкций, не имеющих операндов (например, LODSB) и требующих в некоторых случаях замены сегмента, на данный момент не существует никакого синтаксического способа обойти конструкцию es lodsb.

Инструкции не требуется использовать префиксы: префиксы, такие как CS, A32, LOCK или REPE могут присутствовать в строке самостоятельно и при этом NASM будет генерировать соответствующие префикс-байты.

В дополнение к инструкциям процессора, NASM поддерживает также несколько псевдо-инструкций, описанных в Раздел 2.2.

Операнды инструкций могут принимать несколько форм: они могут быть регистрами (например, AX, BP, EBX, CR0: NASM не использует синтаксис в стиле gas, где имена регистров должны предваряться знаком %), эффективными адресами (см. Раздел 2.3), константами (Раздел 2.5) или выражениями (Раздел 2.6).

Для инструкций сопроцессора NASM допускает различные формы синтаксиса: вы можете использовать двух-операндную форму, поддерживаемую MASMом, а также чисто NASMовскую одно-операндную форму Например, вы можете написать:

        fadd    st1             ; это значит st0 := st0 + st1
        fadd    st0, st1        ; это то же самое

        fadd    st1, st0        ; это значит st1 := st1 + st0
        fadd    to st1          ; это то же самое

Почти любая инструкция сопроцессора, ссылающаяся на содержимое памяти, должна использовать один из префиксов DWORD, QWORD, TWORD, DDQWORD, или OWORD для указания на то, операнд какого размера должен участвовать в команде.