Ассемблирование без секретов

Зоопарк ассемблеров


Ассемблер— это не только язык, но еще и транслятор. То, что "язык" PDP-11 не пригоден для x86 — это понятно, но вот несовместимость ассемблерных трансляторов друг с другом — для многих становится новостью. Что составляет фундамент ассемблера как языка? Мнемоники машинных команд (mov, nop, cmp) – это раз и средства самого языка (метки, директивы, макросы) — это два! Формально, за мнемоники отвечают Intel и AMD. Именно они дают символические имена машинным командам, регистрам, флагам и иже. Большинство x86-ассемблеров придерживаются этой нотации (хоть она никем и не стандартизирована), однако, "большинство" это еще не все. В мире UNIX широко распространен AT&T синтаксис, отличающийся не только синтаксисом, но и порядком операндов! Здесь операнд-приемник расположен не слева, как у Intel, а справа!!! Регистры начинаются со знака процента, константы — со знака доллара, а инструкции имеют суффикс, соответствующий типу обрабатываемых данных. На языке Intel пересылка в регистр eax значения 666h выглядит так: "mov eax,666h", а на AT&T так: "movl $666h,%eax". Как говориться — почувствуете задницу! (И всю плачевность ситуации тоже).

Программа, предназначенная для одного типа ассемблеров, не может быть откомпилирована на другом без радикальной переделки или автоматической конвертации! Но даже среди ассемблеров "своего" типа наблюдается разброд, разнобой и множество различий: в ключевых словах, в правилах оформления листинга, в поставляемых библиотеках и заголовочных файлов и т. д. Если только совместимость не заявлена явно, транслировать программу нужно тем и только тем ассемблером для которого она предназначена. В противном случае — готовьтесь к переделкам (то есть, к адоптации). Отличия зачастую проявляются в самых неожиданных местах. Некоторые ассемблеры понимают, что "mov eax, x" это тоже самое, что и "mov eax,[x]", некоторые — нет. Они спотыкаются и выдают ошибку. Но еще ничего! Гораздо хуже, когда транслятор молчаливо трактует эту конструкцию как "mov eax, offset x", что совсем не одно и тоже! Так что при переносе программы приходится быть очень и очень осторожным.


Совместимость операционных систем — вообще песня. Программы, ориентированные на MS-DOS, без мата не только не транспортабельны, но и непереносимы. Для них характерно прямое взаимодействие с оборудованием, доступное в NT только с ядерного уровня, не говоря уже о том, что 16-разрядный код вызывается из 32-разрядных приложений только через DPMI, да и то не без ухищрений.

Таким образом, прежде чем транслировать ассемблерную программу, необходимо отождествить для какого транслятора и операционной системы она предназначена! С ассемблерными фрагментами, выхваченными из "родного" контекста, приходится еще хуже. Допустим, в некоторой статье описывается интересный антиотладочный прием и приводится ассемблерный код, но как встроить его в свою программу — не говорится. Знакомая ситуация, не правда ли? Непосредственная трансляция невозможна — транслятор дико материться, но ничего не говорит.

Вот обо всем этом мы  и будем говорить, а пока пойдем на балкон и покурим!




Содержание раздела