FAQ для раздела Assembler, MASM, TASM - Assembler - Ответ 5113249

Где скачать компилятор для ассемблера?

Компиляторы языков высокого уровня (Си, Паскаль) в определенной степени совместимы между собой и хотя исходный текст, предназначенный для одного компилятора, не всегда без переделок транслируется на другом, синтаксис и прочие языковые концепции остаются неизменными, позволяя "летать" между MS VC, Intel C++, GCC, Open WATCOM, сравнивая полноту поддержки Стандарта, скорость трансляции, качество кодогенерации, популярность компилятора и вытекающее отсюда изобилие (недостаток) библиотек и компонентов к нему.

С трансляторами ассемблера все обстоит иначе. Казалось бы, x86 ассемблер — он и в Африке ассемблер, но нет! Кроме поддержки мнемоник машинных команд, каждый транслятор обладает своим собственным набором директив и макросредств, зачастую ни с чем не совместимых. Ассемблерный листинг под MASM, бесполезно переносить на FASM, поскольку возможности, предоставляемые макросредствами, у них неодинаковые.

Человеку, упорно игнорирующего существование Linux/BSD, абсолютно все равно, на какое количество платформ был перенесен данный транслятор. А для кого-то это вопрос первостепенной важности!

Тем не менее, существует ряд основополагающих критериев, существенных для всех категорий программистов. Начнем с генерации отладочной информации, без которой отладка программы сложнее, чем "hello, word", превращается в настоящую пытку. Кое-кто попытается возразить, что ассемблерам, в отличии от языков высокого уровня, отладочная информация не нужна, ведь мнемоники машинных команд, что в листинге, что в отладчике — одни и те же. А метки?! А структуры?! А имена функций?! Уберите их — и код станет совершенно не читаемым! Можно воспользоваться отладочной печатью (просто вставлять макрос, выводящий значение регистров/переменных на экран/файл в указанных местах). Еще можно отлаживать программу, держа перед носом распечатку исходных текстов.

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

Если формат отладочной информации — это, скорее, проблема для профессионалов, то формат выходных файлов касается всех. Обыкновенный obj, из которого с помощью линкера можно изготовить все, что угодно — от exe до dll. Объектные файлы делятся на

omf (в редакциях от Microsoft и IBM)
coff, elf, aout
кучу разной экзотики в стиле as86, rdf, ieee и т.д

Также заслуживает внимания возможность "сквозной" генерации двоичных файлов, не требующая помощи со стороны линкера. А некоторые ассемблеры (например, FASM) даже позволяют "вручную" генерировать исполняемые файлы и динамические библиотеки различных форматов, полностью контролируя процесс их создания и заполняя ключевые поля по своему усмотрению. Впрочем, программы, целиком написанные на ассемблере — это либо вирусы, либо демки, либо учебные. Обычно на ассемблере пишутся лишь системно-зависимые компоненты или модули, критичные к быстродействию, которые затем линкуются к основному проекту и, если ассемблер генерирует только omf, а компилятор — coff, тогда возникает проблема сборки "разнокалиберных" форматов воедино. Линкер, умеющий это делать — ulink от Юрия Харона, он же обеспечивает возможности по сборке файлов "вручную", так что выбор конкретного ассемблерного транслятора целиком лежит на совести (и компетенции) программиста, но все-таки лучше, чтобы и ассемблер, и компилятор генерировали одинаковые форматы объектных файлов.

Другой немаловажный критерий — количество поддерживаемых процессорных архитектур, которых в линейке x86 набралось уже больше десятка. Конечно, недостающие команды можно реализовать с помощью макросов или запрограммировать непосредственно в машинном коде через директиву DB, но... если так рассуждать, то зачем вообще нужны ассемблеры, когда есть hex-редакторы?! Особое внимание следует обратить на платформы AMD x86-64 и Intel IA64. 64-разрядные архитектуры вытесняют x86, поэтому учиться программировать под них обязательно, так что поддержка со стороны транслятора должна быть обеспечена уже сейчас!

Ни один из трансляторов не поддерживает набор команд x86-процессоров в полном объеме. Например, на MASM'е невозможно написать jmp 0007h:00000000h и приходится прибегать к различным ухищрениям: либо реализовать команду через DB, что ненаглядно и неудобно, либо заталкивать в стек сегмент/смещение, а потом делать retf, но это длинно и к тому же воздействует на стек, которого у нас может и не быть.

Программирование на смеси 16- и 32-разрядного кода с кратковременным переходом в защищенный режим и возвращением обратно в реальный — на MASM'е скорее умрешь, чем такое запрограммируешь, но большинству программистов подобное трюкачество просто не нужно!

А вот что реально нужно большинству — так это интеграция в мировое сообщество. Свои собственные оси обычно пишут новички, только что начитавшиеся Юрова/Зубкова и открывшие для себя защищенный режим с его безграничными возможностями. В учебном плане это очень даже хорошо, но коммерческим программистам обычно приходится программировать под уже существующие системы — ту же Windows, например. И, если в состав DDK входит MASM в кучей исходных текстов драйверов, то пытаться собрать их под другим транслятором означает впустую убивать время. Опять-таки, если компилятору Microsoft Visual C++ задать ключ /FA, то он выдаст ассемблерный листинг в стиле MASM, точно так же поступит и IDA Pro, Borland C++ выберет TASM, а GCC - GNU Assembler (он же GAS). Вот это и называется интеграцией в среду программирования. Чистый ассемблер сам по себе мало кому интересен и практически всегда становится приложением к чему-то еще. Если вы пишите драйвера под Windows на Microsoft Visual C++, то разумнее всего остановить свой выбор на MASM'е, поклонникам же Borland C++ лучше TASM'а ничего не найти. Под Linux/BSD рулит GAS (GNU Assembler) уже хотя бы за счет того, что ассемблерные программы можно транслировать с помощью компилятора GCC, используя Си-сопроцессор с одной стороны и освобождаясь от головной боли с поиском стартового кода и библиотек, однако GAS использует AT&T-синтаксис, являющийся полной противоположностью Intel-синтаксису, которого придерживаются MASM, TASM, FASM, NASM/YASM. Разработчики вирусов и просто маленьких ассемблерных программ, написанных из любви к искусству, намного меньше ограничены в своем выборе и могут использовать все, что им по душе, вне зависимости от степени "поддержки".

Качество документирования играет весьма важную роль и еще важнее — кому принадлежит проект. Трансляторы, созданные энтузиастами-одиночками, могут умереть в любой момент, поэтому закладываться на них в долговременной перспективе не стоит. Коммерческие ассемблеры крупных компаний выглядят намного более стабильными и непоколебимыми, однако никаких гарантий, что в один "прекрасный" момент компания не забросит на своей продукт, у нас нет (достаточно вспомнить историю с TASM'ом). Открытые трансляторы, поддерживаемые независимой группой лиц, наиболее живучи. Стоило коллективу NASM'а чуть-чуть приостановить его развитие, как тут же появился YASM — "позаимствовавший" исходные тексты и добавивший все необходимое (поддержку x86-64, формат отладочной информации CodeView и так далее).

Последнее, на чем хотелось бы заострить внимание — это макросредства. Отношение к ним у программистов двоякое. Одни во всю пользуются плодами прогресса, программируя на смеси ассемблера, бейсика и препроцессора Си (существует даже проект HLA:

High Level Assembler — Ассемблер Высокого Уровня

), другие — презирают их, ратуя за чистоту ассемблерного кода. Макросы упрощают программирование, зачастую позволяя невозможное (например, шифровать код программы еще на стадии ассемблирования!), но переносимость программы от этого резко ухудшается и переход на другой транслятор становится труднореализуемым. Но как бы там ни было, поддержка макросов совсем не обязывает этими макросами пользоваться!

Вернуться к обсуждению:

FAQ для раздела Assembler, MASM, TASM Assembler