17. Структура программы на языке ассемблера. Модули. Сегменты. - Tulenenok/_Assembler Wiki

Структура программы на ассемблера

Основное, из чего состоит программа – это файлы с исходным кодом. Такие файлы в ассемблере называются модулями.

Основное, что находится в каждом модуле – это описание сегментов (то есть описание блоков памяти).

Внутри сегментов находятся:

  • Команды процессора
  • Инструкции описания структур данных, выделения памяти для переменных и констант
  • Макроопределения

Полный формат строки (все части необязательны):

метка		команда/директива		операнды 		; комментарий

Основное отличие директив и кодов команд состоит в том, что в процессе ассемблирования директивы предоставляют программе-ассемблеру вспомогательную информацию, которая используется в процессе ассемблирования и служит для описания типов данных, резервирования памяти, определения сегментов, организаций процедур и т. п.

Метки

Записываются по-разному, в зависимости от того, где он применяются.

В коде

  • Имя метки обязательно отделяется двоеточием
  • Имя может состоять из латинских букв, цифр (не могут идти в начале), знаков подчеркивания и еще нескольких спец символов
  • Обычно используются в командах передачи управления
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 (модель памяти)

.model модель, язык, модификатор

Нужны для сокращения записи программ определенных типов

Модели

  • TINY – один сегмент на все (пример – COM программа)
  • SMALL – код в одном сегменте, данные и стек – в другом
  • COMPACT – допустимо несколько сегментов данных
  • MEDIUM – код в нескольких сегментах, данные в одном
  • LARGE, HUGE

Язык: C, PASCAL, BASIC, SYSCALL, STDCALL.

(этот параметр нужен для связывания с языками высокого уровня и вызова подпрограмм, то есть на случай, если мы код на ассемблере захотим подключить куда-нибудь)

Модификатор – способ подключения стека:

  • NEARSTACK – ближний
  • FARSTACK – дальний

Директива END

…
END [точка_входа]

Этой директивой должно заканчиваться описание любого модуля.

точка_входа – имя метки в сегменте кода, указывающей на команду, с которой начнется исполнение программы.

Если в программе несколько модулей, то только один может содержать точку входа.

Директива ASSUME

ASSUME регистр : имя сегмента

Не является командой

Нужна для контроля компилятором правильности обращения к переменным

Code SEGMENT WORD 'CODE'
   assume CS:Code