fasm

Материал из Википедии — свободной энциклопедии
(перенаправлено с «FASM»)
Перейти к навигации Перейти к поиску

flat assembler
Скриншот программы flat assembler
Скриншот FASM с кодом из поставляемых примеров
Тип компилятор
Разработчик Томаш Грыштар
Написана на язык ассемблера
Операционная система Unix-подобная операционная система, Microsoft Windows, MS-DOS, DOS, Linux, OpenBSD, MenuetOS и KolibriOS
Первый выпуск 1999
Последняя версия 1.73.30[1] (21 февраля 2022; 11 месяцев назад (2022-02-21))
Создаваемые форматы файлов Executable and Linkable Format, COFF и Portable Executable
Лицензия 2-пунктная лицензия BSD[d][2]
Сайт flatassembler.net​ (англ.)

fasm (сокр. от flat assembler) — свободно распространяемый многопроходной ассемблер, написанный Томашем Грыштаром (польск. Tomasz Grysztar). fasm самодостаточен[1], изначально компилировался TASM-ом и стал способен собираться из собственных исходных кодов начиная с 4 мая 1999 в версии 0.90. fasm обладает небольшими размерами и очень высокой скоростью компиляции[источник не указан 379 дней], имеет богатый и ёмкий макро-синтаксис, позволяющий автоматизировать множество рутинных задач[3][4]. Поддерживаются как объектные форматы, так и форматы исполняемых файлов. Это позволяет в большинстве случаев обойтись без компоновщика. В остальных случаях нужно использовать сторонние компоновщики, поскольку таковой вместе с fasm не распространяется.

Помимо базового набора инструкций процессора и сопроцессора[каких?], fasm поддерживает наборы инструкций MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, SSE4a, AVX, AVX-2, AVX-512, 3DNow!, дополнительные расширения AES, CLMUL, FMA, FMA4, XOP, а также EM64T и AMD64 (включая AMD SVM и Intel SMX).

Все вариации fasm непосредственно могут создавать выходные файлы в следующих, предустановленных в ассемблер, форматах: объектные файлы (стандартно для большинства ассемблеров): Executable and Linkable Format (ELF) или Common Object File Format(COFF)(классический или в спецификации микрософт), исполняемые файлы (не требует дополнительных компоновщиков): MZ, ELF или Portable Executable (PE) (WDM драйвера включительно, с возможностью настройки MZ DOS stub). Для генерации файлов в формате, отличном от предустановленных, есть формат бинарный файл, дающий программисту полный контроль за каждым байтом выходного файла, однако всю структуру, содержание и взаимосвязи такого файла программисту придётся описывать непосредственно.

В качестве родной целевой архитектуры используются архитектуры IA32 и x86-64. Присутствует неофициальное дополнение fasmarm, в котором родные целевые архитектуры ARM и ARM64. Реализация целевых архитектур, отличных от родной, аналогична подобной реализации на любом другом ассемблере - для этих целей используются макрокоманды и директивы определения данных.

Компиляция[править | править код]

Компиляция программы в fasm состоит из трёх стадий: препроцессирование, синтаксический анализ и ассемблирование.

Препроцессирование[править | править код]

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

Синтаксический анализ[править | править код]

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

Ассемблирование[править | править код]

На стадии ассемблирования определяются адреса меток, обрабатываются условные директивы, раскрываются циклы и генерируется собственно программа. fasm — многопроходной ассемблер, что позволяет ему делать некоторые оптимизации (например, генерировать короткий переход на метку вместо длинного). Во время прохода компилятор не всегда может вычислить выражение в условных директивах. В этом случае он делает какой-нибудь выбор и пытается скомпилировать дальше. Благодаря тому, что адреса меток, вычисленные на N-м проходе, используются на N+1-м проходе, этот процесс обычно сходится.

История[править | править код]

Проект был начат в 1999 году Томашом Грыштаром (польск. Tomasz Grysztar), который на тот момент был студентом. Его исходный код был полностью написан на языке ассемблера TASM. Начиная с версии 0.90 (4 мая 1999) ассемблер fasm стал самодостаточен(его исходный код был адаптирован под родной диалект и собирался самим ассемблером fasm). В марте 2000 года fasm был опубликован в сети Интернет.

Изначально fasm запускался только из 16-разрядного плоского реального режима. Затем была добавлена поддержка 32-разрядности и в дополнение к ней поддержка DPMI. Исходный код был переписан таким образом, чтобы его легко можно было портировать под любую x86 операционную систему, поддерживающую 32-битную адресацию. Он был портирован на Windows, затем на Linux.

Принципы[править | править код]

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

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

Fasm не включает в выходной файл объявления не используемых процедур (реализовано посредством макрокоманд).

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

Исходный код для fasm может собираться сразу в исполняемый файл, минуя стадии создания промежуточных объектных файлов и их компоновки.

Процесс компиляции[править | править код]

Компиляция исходного кода проходит в несколько изолированных друг от друга стадий.

Приведение выходных данных к запрошенному формату[править | править код]

Блоки выходных данных обрамляются необходимыми для формата заголовками, обрабатываются взаимосвязи данных и заголовков, рассчитываются контрольные суммы, размеры блоков... Генерируется выходной файл.

Формат записи инструкций[править | править код]

Используется Intel-синтаксис записи инструкций.

Единственное существенное отличие от формата, принятого в других ассемблерах (MASM, TASM в режиме совместимости с MASM) — значение ячейки памяти всегда записывается как [label_name], а просто label_name означает адрес (то есть порядковый номер) ячейки. Это позволяет обходиться без ключевого слова offset. Также в fasm при переопределении размера операнда вместо byte ptr пишется просто byte, вместо word ptr — word и т. д. Не позволяется использовать несколько квадратных скобок в одном операнде — таким образом, вместо [bx][si] необходимо писать [bx+si]. Эти изменения синтаксиса привели к более унифицированному и лёгкому для чтения коду.

Пример программы[править | править код]

Пример Windows-программы «Hello, world!», которая выводит это сообщение с помощью функции MessageBox и завершается:

         format  pe gui 4.0
         entry   start
         include 'win32a.inc'

 start:
         invoke  MessageBox,NULL,message,message,MB_OK
         invoke  ExitProcess,0

 message db 'Hello, World!',0

         data    import
         library kernel32,'kernel32.dll',\
                 user32,'user32.dll'
         include 'api/kernel32.inc'
         include 'api/user32.inc'
         end     data

Или так:

         include 'win32ax.inc'
 .code
 main:
         invoke  MessageBox,NULL,'Hello, World!','Fasm message box:',MB_OK
         invoke  ExitProcess,0
 .end main

Усложнённый вариант, с уточнением секций в PE-файле:

         format  pe gui
         entry   start
         include 'win32a.inc'

 section '.data' data readable writeable

 message db      'Hello, World!',0

 section '.code' code readable executable

 start:
         invoke  MessageBox,NULL,message,message,MB_OK
         invoke  ExitProcess,0

 section '.idata' import data readable writeable
         library kernel32,'kernel32.dll',\
                 user32,'user32.dll'
         import  kernel32,\
                 ExitProcess,'ExitProcess'
         import  user32,\
                 MessageBox,'MessageBoxA'

Пример простой консольной программы в формате .COM:

        org      100h

        mov      ah,9h
        mov      dx,hello
        int      21h
        mov      ah,8h
        int      21h
        int      20h

 hello  db       13,10,"Hello, World!$"

Пример простой программы в формате ELF.

format ELF executable 3
entry start

segment readable executable

start:
        mov     eax,4
        mov     ebx,1
        mov     ecx,msg
        mov     edx,msg_size
        int     0x80

        mov     eax,1
        xor     ebx,ebx
        int     0x80

segment readable writeable

msg db 'Hello world!',0xA
msg_size = $-msg

Формат выходных файлов[править | править код]

С помощью директивы format можно указать следующие форматы выходных файлов:

  • MZ — исполняемые файлы DOS.
  • PE — исполняемые файлы Windows (консольные, графические приложения и динамические библиотеки).
    • PE64 — исполняемые файлы 64-битных версий Windows.
  • COFF, MS COFF, MS64 COFF — объектные файлы.
  • ELF, ELF64 — исполняемые файлы в Unix-подобных системах.
  • ARM — разработка энтузиастов [5].
  • Binary — файлы произвольной структуры. Указав смещение 100h (org 100h), можно получить исполняемый файл формата .COM. Также с помощью format binary можно компилировать файлы данных[6].

Операционные системы[править | править код]

  • DOS;
  • Windows: NT, XP, Vista, 7;
  • Основанные на Linux — напрямую, через системные вызовы;
  • FreeBSD;
  • Другие, основанные на libc (Unix-подобные);
  • MenuetOS, KolibriOS — не поставляется в стандартном пакете fasm, поставляется вместе с этими операционными системами.

Применение[править | править код]

Операционные системы, написанные на FASM:

  • DexOS — автор Ville Turijanmaa
  • MenuetOS — 32- и 64-битные графические операционные системы, автор Ville Turijanmaa
  • KolibriOS — форк MenuetOS

Компиляторы, использующие FASM как бекэнд ассемблер:

IDE, основанное на FASM:

  • Fresh — проект, поддерживаемый интернет сообществом, основанный John Found

Поддержка fasm в сторонних программных продуктах[править | править код]

Файл поддержки синтаксиса fasm поставляется вместе с базовым пакетом Vim.

Использование fasm поддерживают многие специализированные IDE, такие как RadASM, WinAsm Studio, Fresh (специально спроектированный под fasm) и т. д.

Интересные факты[править | править код]

  • При всей своей открытости (наличие исходного кода в репозитории на github) FASM - нельзя полноценно считать Open Source-проектом, т.к. в исходном тексте на ассемблере присутствуют только символические имена меток и переменных. Ни рабочие структуры, ни отладочная информация в открытом доступе не показаны.

Примечания[править | править код]

  1. 1 2 Flat assembler download (англ.). flatassembler.net. Дата обращения: 26 августа 2019. Архивировано 31 августа 2019 года.
  2. https://github.com/tgrysztar/fasm/blob/752cc50465e38a98a2b6ed1161983988e4d5f61a/LICENSE.TXT
  3. Tomasz Grysztar. Flat Assembler Programmer’s Manual (англ.) (недоступная ссылка — история). Дата обращения: 27 мая 2012. Архивировано 31 мая 2012 года.
  4. Randall Hyde. Which Assembler is the Best? (англ.) (недоступная ссылка — история). Дата обращения: 27 мая 2012. Архивировано 31 мая 2012 года.
  5. FASM ARM (англ.). flatassembler.net.
  6. Тема на официальном форуме о создании изображений с помощью макросов fasm (англ.). Дата обращения: 26 августа 2019. Архивировано 4 августа 2020 года.

Ссылки[править | править код]