17. Структура программы на языке ассемблера. Модули. Сегменты.
Основное, из чего состоит программа – это файлы с исходным кодом. Такие файлы в ассемблере называются модулями.
Основное, что находится в каждом модуле – это описание сегментов (то есть описание блоков памяти).
Внутри сегментов находятся:
- Команды процессора
- Инструкции описания структур данных, выделения памяти для переменных и констант
- Макроопределения
Полный формат строки (все части необязательны):
метка команда/директива операнды ; комментарий
Основное отличие директив и кодов команд состоит в том, что в процессе ассемблирования директивы предоставляют программе-ассемблеру вспомогательную информацию, которая используется в процессе ассемблирования и служит для описания типов данных, резервирования памяти, определения сегментов, организаций процедур и т. п.
Записываются по-разному, в зависимости от того, где он применяются.
В коде
- Имя метки обязательно отделяется двоеточием
- Имя может состоять из латинских букв, цифр (не могут идти в начале), знаков подчеркивания и еще нескольких спец символов
- Обычно используются в командах передачи управления
mov cx, 5
label1:
add ax, bx
loop label1 ; цикл выполняется 5 раз
В данных
- Используются для объявления переменных или констант
- label – ключевое слово, для определения переменной
- Возможные типы:
- BYTE – 1 байт
- WORD – 2 байта
- DWORD – 4 байта
- FWORD – 6 байт
- QWORD – 8 байт
- TBYTE – 10 байт
// И два доп типа для хранения меток в коде, адресов команд
- NEAR – метка ближнего перехода
- FAR – метка дальнего перехода
метка label тип
Использование в макросах
метка EQU выражение (EQU можно заменить на =)
Директива – инструкция ассемблеру, влияющая на процесс компиляции и не являющаяся командой процессора. Обычно не оставляет следов в формируемом машинном коде.
Псевдокоманда – директива ассемблера, которая приводит к включению данных или кода в программу, нот не соответствующая никакой команде процессора.
Псевдокоманды определения данных указывают, что в соответствующем месте располагается переменная, резервируют под нее место заданного типа, заполняют значением и ставят в соответствие метку.
Виды: DB(1), DW(2), DD(4), DF(6), DQ(8), DT(10)
float_number DD 3.5e7
text_string DB ‘Hello world!’
Каждая программа, написанная на любом языке программирования, состоит из одного или нескольких сегментов. Обычно область памяти, в которой находятся команды, называют сегментом кода, область памяти с данными - сегментом данных и область памяти, отведенную под стек, - сегментом стека.
имя SEGMENT [READONLY] [выравнивание] [тип] [разрядность] [‘класс’]
…
имя ENDS
READONLY – если во время выполнения компилятор увидит, что идет попытка записи в этот сегмент, компиляция будет остановлена с ошибкой.
Выравнивание – обозначает с каких адресов будет начинаться сегмент:
- BYTE – сегмент может начаться с произвольного адреса
- WORD – сегмент всегда начинается с адреса, кратного 2
- DWORD – сегмент всегда начинается с адреса, кратного 4
- PARA – сегмент всегда начинается с начала параграфа (адреса, кратного 16) ! это значение по умолчанию
- PAGE – сегмент начинается с адреса, кратного 256
Тип
- PUBLIC – сегменты с одним именем будут располагаться в памяти непосредственно друг за другом, независимо от того, в каком порядке они были объявлены в исходном коде
- STACK – сегмент будет использоваться под стек. Все сегменты в исходном коде с таким типом будут объединяться в один для увеличения размера стека.
- COMMON – сегменты также будут объединяться, но не друг за другом, а как бы накладываться (те начинаться с одного и того же адреса)
- AT – должен иметь определенный аргумент (номер параграфа начала сегмента), обозначает, что сегмент будет загружаться в память по некоторому фиксированному постоянному адресу (вне зависимости от других сегментов)
- PRIVATE – сегмент не объединяется с другими, существует сам по себе !это значение по умолчанию
Класс – любая метка, взятая в одинарные кавычки. Сегменты одного класса будут расположены в памяти друг за другом.
.model модель, язык, модификатор
Нужны для сокращения записи программ определенных типов
Модели
- TINY – один сегмент на все (пример – COM программа)
- SMALL – код в одном сегменте, данные и стек – в другом
- COMPACT – допустимо несколько сегментов данных
- MEDIUM – код в нескольких сегментах, данные в одном
- LARGE, HUGE
Язык: C, PASCAL, BASIC, SYSCALL, STDCALL.
(этот параметр нужен для связывания с языками высокого уровня и вызова подпрограмм, то есть на случай, если мы код на ассемблере захотим подключить куда-нибудь)
Модификатор – способ подключения стека:
- NEARSTACK – ближний
- FARSTACK – дальний
…
END [точка_входа]
Этой директивой должно заканчиваться описание любого модуля.
точка_входа
– имя метки в сегменте кода, указывающей на команду, с которой начнется исполнение программы.
Если в программе несколько модулей, то только один может содержать точку входа.
ASSUME регистр : имя сегмента
Не является командой
Нужна для контроля компилятором правильности обращения к переменным
Code SEGMENT WORD 'CODE'
assume CS:Code