Язык ассемблера - Базовый синтаксис

В этой главе описываются базовая структура, правила синтаксиса и соглашения о написании программ на ассемблере NASM, помогая вам понять скелет кода на ассемблере.


Базовая структура программы на ассемблере

Полная программа на ассемблере NASM обычно состоит из следующих частей:

Пример

; Путь к файлу: structure.asm
; Пример базовой структуры программы на NASM

section .data                       ; Секция данных: хранит инициализированные данные
    ; Определите переменные и константы здесь
    msg db 'Hello, EXAMPLE!', 0xA
    len equ $ - msg

section .bss                        ; Секция BSS: хранит неинициализированные данные
    ; Здесь зарезервировать область памяти
    buffer resb 64                  ; Зарезервировать буфер размером 64 байта

section .text                       ; Секция кода: хранит исполняемые инструкции
    global _start

_start:
    ; Здесь напишите логику программы
    mov eax, 4
    mov ebx, 1
    mov ecx, msg
    mov edx, len
    int 0x80

    mov eax, 1
    mov ebx, 0
    int 0x80
РазделНазначениеХарактеристики
.dataХранит инициализированные глобальные переменные и константыРазмер и содержимое определяются во время компиляции, хранятся в исполняемом файле
.bssХранит неинициализированные глобальные переменныеПространство выделяется только во время выполнения, не занимает размер исполняемого файла
.textХранит исполняемые машинные инструкцииТолько для чтения, содержит весь логический код программы

Как минимум.textсекции требуются для формирования корректной программы на ассемблере. Если данных нет, можно опустить.dataи.bssсекцию.


Формат инструкции ассемблера

Общий формат каждой инструкции ассемблера:

[标签:]   指令助记符   [操作数1 [, 操作数2 [, 操作数3]]]   [; 注释]

Пояснение каждой части:

ЧастьОбязательно?Описание
LabelOptionalСимволическое имя, представляющее адрес памяти, заканчивающееся двоеточием
Мнемоника инструкцииОбязательныйНапример, mov, add, sub и т. д., сообщает процессору, что делать
ОперандНеобязателен (у некоторых инструкций нет операнда)Объект данных, с которым работает инструкция; может быть регистром, адресом памяти или непосредственным значением
КомментарийOptionalНачинается с точки с запятой и продолжается до конца строки

Пример

; Примеры различных форматов инструкций

; Только инструкция, без операнда
ret                     ; Возврат из подпрограммы

; Инструкция + один операнд
push eax                ; Поместить значение eax в стек
inc ecx                 ; Увеличить ecx на 1

; Инструкция + два операнда (наиболее распространённый случай)
mov eax, 42             ; Скопировать 42 в регистр eax
add ebx, ecx            ; ebx = ebx + ecx

; С меткой
loop_start:             ; Метка: обозначает начало цикла
    dec ecx             ; Вычесть 1 из ecx
    jnz loop_start      ; Если ecx не равен 0, перейти обратно к loop_start

Соглашения о комментариях

NASM используетточку с запятой (;)для обозначения комментариев; содержимое от точки с запятой до конца строки игнорируется ассемблером.

Пример

; Комментарий на всю строку: объясняет назначение следующего блока кода
; Вычислить сумму двух чисел и вывести результат

mov eax, 10             ; Комментарий в строке: поместить 10 в eax
add eax, 20             ; Комментарий в строке: добавить 20 к eax, теперь eax = 30

Комментарии чрезвычайно важны в коде на ассемблере. Без комментариев даже автор может не понять код на ассемблере через несколько недель. Выработайте привычку писать комментарий к каждой инструкции.


Правила именования идентификаторов

Идентификаторы (метки, имена переменных, имена констант и т. д.) должны подчиняться следующим правилам:

ПравилоОписание
Символы, входящие в составБуквы, цифры, подчёркивание _, точка ., вопросительный знак ?, @, $, # и т. д.
Начальный символДолжно начинаться с буквы, подчёркивания, точки или вопросительного знака; не может начинаться с цифры.
Чувствительность к региструПо умолчанию чувствительны к регистру (можно изменить с помощью параметров компиляции)
Зарезервированные словаНе могут иметь такое же имя, как мнемоники инструкций, имена регистров или ключевые слова NASM.

Пример

; Допустимые идентификаторы
my_variable:            ; Начинается с буквы + подчёркивания
.loop_start:            ; Начинается с точки (локальная метка)
?error_handler:         ; Начинается с вопросительного знака
counter2:               ; Буква + цифра

; Недопустимые идентификаторы (только для справки, не используйте)
; 1st_value: ; Ошибка: не может начинаться с цифры
; mov: ; Ошибка: mov — зарезервированное слово
; my-variable: ; Ошибка: дефис не является допустимым символом

Псевдоинструкции (директивы)

ДирективыЭто команды для ассемблера, а не инструкции для процессора; они управляют процессом ассемблирования и определяют структуры данных.

ДирективыНазначениеПример
dbОпределить байт (1 байт)byte_val db 0x55
dwОпределить слово (2 байта)word_val dw 0x1234
ddОпределить двойное слово (4 байта)dword_val dd 0x12345678
equОпределить константуMAX_SIZE equ 256
resbЗарезервировать байтовое пространствоbuffer resb 128
reswЗарезервировать пространство под словоwbuf resw 64
resdЗарезервировать пространство под двойное словоdbuf resd 32
%defineКонстанта, определённая макросом%define COUNT 10

Соглашения о регистре

NASM по умолчанию для меток и идентификаторовчувствителен к регистру.:

Пример

; Пример чувствительности к регистру

section .data
    msg db 'EXAMPLE', 0       ; Определить переменную msg

section .text
    global _start

_start:
    mov eax, MSG             ; Ошибка: MSG и msg различаются (если только не включён режим нечувствительности к регистру)
    mov eax, msg             ; Верно: msg точно совпадает с определением

    MOV EAX, 42              ; Синтаксически верно: мнемоники инструкций нечувствительны к регистру
    mov eax, 42              ; Рекомендуемый стиль: используйте нижний регистр для лучшей читаемости

Мнемоники инструкций и имена регистров нечувствительны к регистру (MOV、Mov、movтот же эффект), но рекомендуемый стиль — единообразно в нижнем регистре.


Числовое представление

NASM поддерживает числовое представление в нескольких системах счисления:

Пример

; Представление различных систем счисления в NASM

mov eax, 42             ; Десятичное: запишите число напрямую
mov eax, 0x2A           ; Шестнадцатеричное: 0x (рекомендуемый стиль)
mov eax, 2            ; Шестнадцатеричное: суффикс h
mov eax, 0o52           ; Восьмеричное: префикс 0o
mov eax, 52o            ; Восьмеричное: суффикс o
mov eax, 101010b        ; Двоичное: суффикс b
mov eax, 0b101010       ; Двоичное: префикс 0b

Рекомендуется:0xиспользуйте префикс для шестнадцатеричных чисел (например,0x2A), поэтому его меньше шансов спутать с метками.


Полный пример синтаксиса

Следующая программа всесторонне использует вышеуказанные элементы синтаксиса, чтобы вычислить сумму чисел от 1 до 10 и вывести её:

Пример

; Путь к файлу: sum.asm
; Вычислить 1+2+...+10 и вывести полученный символ

section .data
    result db 0                 ; Сохранить результат вычисления (1 байт)
    newline db 0xA              ; Символ новой строки

section .text
    global _start

_start:
    ; Инициализировать регистры и переменные
    mov ecx, 10                 ; Счётчик цикла: обратный отсчёт от 10
    mov eax, 0                  ; eax хранит накопленную сумму, изначально 0

sum_loop:                       ; Метка начала цикла
    add eax, ecx                ; eax = eax + ecx
    dec ecx                     ; ecx уменьшается на 1
    jnz sum_loop                ; Если ecx != 0, продолжить цикл

    ; На этом этапе eax = 55 (10+9+...+1)
    add eax, '0'                ; Преобразовать число в ASCII-символ ('0'=48, 55+48=103='g', неверно)
                                ; Фактическая демонстрация требует более сложного преобразования, см. в последующих главах

    ; Здесь выводится только результат (упрощённая демонстрация)
    mov [result], al            ; Сохранить накопленный результат в result

    ; Выход из программы
    mov eax, 1
    mov ebx, 0
    int 0x80

Примечание: в приведённом выше примере прямое добавление '0' корректно только тогда, когда число находится в диапазоне 0-9. Преобразование чисел с двумя или более цифрами будет подробно объяснено в последующих главах.

Другие расширения