Есть ещё один особый случай — когда препроцессор собирается проверить второй символ и натыкается на двоеточие (что далее интерпретируется ассемблером как определение метки), он останавливается в этом месте и заканчивает препроцессинг первого символа (то есть если это символьная константа, она развертывается) и если это все еще выглядит меткой, совершается стандартный препроцессинг, начиная с места после метки. Это позволяет поместить директивы препроцессора и макроинструкции после меток, аналогично инструкциям и директивам, обрабатываемым ассемблером, например:
start: include 'start.inc'
Однако если метка во время препроцессинга разрушается (например, если у символьной константы пустое значение), происходит только замена символьных констант до конца строки.
2.4 Директивы форматирования
«format
» со следующим за ним идентификатором формата позволяет выбрать формат вывода. Эта директива должна стоять в начале кода. Формат вывода по умолчанию — это простой двоичный файл, он может быть также выбран директивой «format binary
».
«use16
» и «use32
» указывают ассемблеру генерировать 16-битный или 32-битный код, пренебрегая настройкой по умолчанию для выбранного формата вывода. «use64
» включает генерирование кода для длинного режима процессоров x86.
Ниже описаны разные форматы вывода со специфичными для них директивами.
2.4.1 MZ
Чтобы выбрать формат вывода MZ, используйте директиву «format MZ
». По умолчанию код для этого формата 16-битный.
«segment
» определяет новый сегмент, за ним должна следовать метка, чьим значением будет номер определяемого сегмента. Опционально за этой директивой может следовать «use16
» или «use32
», чтобы указать битность кода в сегменте. Начало сегмента выровнено по параграфу (16 байт). Все метки, определенные далее, будут иметь значения относительно начала этого сегмента.
«entry
» устанавливает точку входа для формата MZ, за ней должен следовать дальний адрес (имя сегмента, двоеточие и смещение в сегменте) желаемой точки входа.
«stack
» устанавливает стек для MZ. За директивой может следовать числовое выражение, указывающее размер стека для автоматического создания, либо дальний адрес начального стекового фрейма, если вы хотите установить стек вручную. Если стек не определен, он будет создан с размером по умолчанию в 4096 байт.
«heap
» со следующим за ней значением определяет максимальный размер дополнительного места в параграфах (это место в добавление к стеку и для неопределенных данных). Используйте «heap 0
», Чтобы всегда отводить только память, которая программе действительно нужна.
2.4.2 PE
Чтобы выбрать формат вывода PE, используйте директиву «format PE
», за ней могут следовать дополнительные настройки формата: используйте «console
», «GUI
» или оператор «native
», чтобы выбрать целевую субсистему (далее может следовать значение с плавающей точкой, указывающее версию субсистемы), «DLL
» помечает файл вывода как динамическую связывающую библиотеку. Далее может следовать оператор «at
» и числовое выражение, указывающее базу образа PE и далее опционально оператор «on
» со следующей за ним строкой в кавычках, содержащей имя файла, выбирающей заглушку MZ для PE программы (если указанный файл не в формате MZ, то он трактуется как простой двоичный исполняемый файл и конвертируется в формат MZ). По умолчанию код для этого формата 32-битный. Пример объявления формата PE со всеми свойствами:
format PE GUI 4.0 DLL at 7000000h on 'stub.exe'
«section
» определяет новую секцию, за ней должна следовать строка в кавычках, определяющая имя секции, и далее могут следовать один или больше флагов секций. Возможные флаги такие: «code
», «data
», «readable
», «writeable
», «executable
», «shareable
», «discardable
», «notpageable
». Начало секции выравнивается по странице (4096 байт). Пример объявления секции PE:
section '.text' code readable executable
Вместе с флагами также может быть определен один из специальных идентификаторов данных PE, отмечающий всю секцию как специальные данные, возможные идентификаторы: «export
», «import
», «resource
» и «fixups
». Если секция помечена для содержания настроек адресов, они генерируются автоматически, и никаких данных определять больше не требуется. Также данные ресурсов могут быть сгенерированы автоматически из файлов ресурсов, этого можно добиться, написав после идентификатора «resourse
» оператор «from
» и имя файла в кавычках. Ниже вы можете увидеть примеры секций, содержащих некоторые специальные данные: