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

Спецификация синтаксиса ассемблерных вставок в среде Delphi
Ассемблерная вставка в Delphi реализуется через конструкцию asm…end, которая строго следует синтаксису Borland Turbo Assembler (TASM). Ключевое отличие от внешних ассемблерных модулей: вставка не требует отдельной компиляции — код на ассемблере обрабатывается непосредственно компилятором Delphi как часть процедуры или функции. Материал вставки размещается между ключевыми словами без дополнительных директив сегментации. Каждый оператор завершается точкой с запятой. Допускаются только команды процессора x86 (архитектура IA-32) — использование инструкций SSE/AVX возможно, но требует явного указания префиксов.
Регистровая модель и соглашение о вызовах
При работе с ассемблерными вставками внутри функций Delphi действует жесткое соглашение о распределении регистров:
- EAX — регистр возврата значения (для типов Integer, Pointer, Char).
- EBX — должен сохраняться вызываемой стороной (callee-save).
- ECX и EDX — аргументы для соглашения register (первые два параметра передаются через них).
- ESI и EDI — callee-save регистры; их текущее значение требуется восстановить перед выходом из вставки.
- ESP и EBP — управление стеком и базой кадра; модификация ESP без соответствующей коррекции ведет к критическому сбою.
Компилятор Delphi автоматически генерирует пролог и эпилог для процедуры, содержащей ассемблерный блок. Манипуляции с регистрами внутри asm/end не должны нарушать целостность стека — каждое изменение EBP или ESP должно быть обратно симметричным к моменту завершения блока. Для передачи дополнительных параметров через стек используется смещение относительно EBP.
Материал и ограничения при работе с памятью
Внутри ассемблерной вставки запрещено использовать динамические строки Delphi (AnsiString, WideString) напрямую — управление ссылками на них требует вызова специальных intrinsic-функций компилятора через директивы, выполняемые вне ассемблерного контекста. Для работы с массивами или записями (record) необходимо передавать указатель через регистр или стек, используя адресную арифметику. Материал данных, на который ссылается вставка, должен располагаться в сегменте данных приложения — прямой доступ к глобальным переменным возможен через их символьные имена. Компилятор подставляет фактические адреса на этапе линковки. Дифференциация от альтернатив (например, Intel C++ Compiler для вставок __asm): Delphi не поддерживает вложенные комментарии и макросы внутри ассемблерного блока, а также не допускает использование локальных меток с точкой.
Процесс генерации команд и стандарты выравнивания
Компилятор Delphi при обработке ассемблерной вставки не выполняет оптимизацию перестановки инструкций — каждая команда занимает строго свою позицию. Однако он принудительно выравнивает начало блока по границе 4 байт (для версий до 2010 года) или 16 байт (начиная с Delphi XE и позднее), что критично для инструкций, требующих выровненных операндов (например, MOVDQA). Качество итогового машинного кода целиком зависит от разработчика: компилятор не вставляет префиксы блокировки (LOCK) для многопоточности — их необходимо добавлять вручную к атомарным операциям. Стандартным требованием к промышленному коду является явная очистка регистров после завершения вставки, если они не входят в callee-save слот (EAX, ECX, EDX).
Технические различия с ассемблерными модулями (файлы .asm)
При выборе между вставкой и внешним ассемблерным модулем необходимо учитывать следующие спецификации:
- Генерация объектного файла: вставка не требует отдельного файла .obj — код встраивается непосредственно в машинный код функции Delphi, что ускоряет сборку, но усложняет отладку (отсутствие символов для отладчика в стиле TD32).
- Контроль типов: в ассемблерной вставке компилятор проверяет только синтаксис инструкций, но не типы операндов — приведение указателей и работа с размером данных (BYTE, WORD, DWORD) ложится на разработчика.
- Поддержка макросов: в отличие от отдельного модуля, где доступны макроподстановки TASM/MASM, вставка ограничена прямыми командами и не поддерживает REPT, EQU и т.д.
- Совместимость с 64-битной архитектурой: начиная с Delphi 2010 (версия 14.0) ассемблерные вставки полностью удалены при компиляции в режиме Win64 — для 64-битных приложений требуется использовать исключительно внешние ассемблерные библиотеки или переходить на Pure Pascal.
Тестирование и контроль целостности вставок
Верификация корректности ассемблерной вставки выполняется через визуальный анализ листинга (опция компилятора $O- и отображение инструкций в CPU-окне отладчика). Стандарты качества в промышленной разработке (ISO 26262, MISRA для embedded) требуют документирования каждого регистра, изменяемого внутри блока, и подтверждения отсутствия side-эффектов на глобальные переменные. Практическое тестирование включает прогон с избыточным количеством итераций для выявления ошибок переполнения стека или неправильного выравнивания. Рекомендуется использовать ассемблерные вставки только в критических по производительности участках (криптографические примитивы, кодеки, низкоуровневый ввод-вывод), где выигрыш в тактах процессора превышает 20% по сравнению с эквивалентом на Delphi, подтверждённый профилированием не менее чем на трёх различных поколениях CPU семейства x86.
Добавлено: 27.04.2026
