Расширенный ассемблер: NASM

Приложение | Предыдущая глава | Содержание | Указатель

Глава 10: Разрешение проблем

Перевод: AsmOS group, © 2001

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

10.1 Общие проблемы

10.1.1 Генерация NASM неэффективного кода

Я получаю много сообщений об ошибках, в которых говорится, что NASM генерирует неэффективный или неверный (при использовании инструкций типа ADD ESP, 8) код. Это преднамеренная особенность дизайна, связанная с предсказуемостью вывода: видя инструкцию типа "ADD ESP, 8", NASM генерирует команду, оставляющую место для 32-битного смещения. Если вы хотите использовать оптимизированную по размеру инструкцию, то должны использовать "ADD ESP, BYTE 8". Это не ошибка, это просто моя точка зрения.

10.1.2 Мои "JUMPы" вне диапазона

Также люди жалуются, что когда они используют переходы по условию (которые являются типа SHORT по умолчанию), которые пытаются перейти слишком далеко, то NASM сообщает "SHORT JUMP OUT OF RANGE", вместо использования более длинного перехода.

Это снова частичная проблема предсказуемости, имеющая также практическую причину. NASM не имеет возможности узнать, для какого типа процессора будет использоваться этот код, так что он не может решить сам использовать переход типа NEAR, потому что не знает, что программа предназначается для процессора 386 и выше. Аналогично, NASM может заменить инструкцию JNE типа SHORT, которая пыталась бы выйти за диапазон, на более короткую команду JE, использующей JUMP NEAR — это разумное решение для процессоров ниже 386, но не эффективное для процессоров, имеющих хорошее предсказание перехода и в состоянии осуществить JMP NEAR. Так что, повторяю — это пользователю, а не ассемблеру решать, какие команды должны быть сгенерированы.

Люди, пишущие загрузочный сектор в двоичном формате, часто жалуются, что ORG работает не так, как им хотелось бы: чтобы поместить сигнатуру 0xAA55 в конец 512-ти байтного загрузочного сектора, те, кто привык к MASM, имеют тенденцию делать следующее

ORG 0 ; код загрузчика ORG 510 DW 0xAA55

В NASM ORG не предназначена для этого. Правильный способ заключается в использовании директивы TIMES: ORG 0 ; код загрузчика TIMES 510-($-$$) DB 0 DW 0xAA55

Директива TIMES вставит необходимое количество нулей в код вплоть до 510-го байта. Еще одно преимущество этого метода в том, что если вы выйдете за допустимые размеры загрузочного сектора, то NASM перехватит эту ошибку еще во время ассемблирования и сообщит об этом, так что вам не придется "доводить" программу дизассемблированием и поиском ошибки.

10.1.4 TIMES не работает

Другая обычная проблема с вышеупомянутым кодом бывает у тех, кто пишет

TIMES 510-$ DB 0

полагая, что $ - это просто число (как и 510), и что разница тоже будет числом и эту разницу можно спокойно преподнести TIMES.

NASM — модульный ассемблер: различные составляющие части разработаны так, чтобы их было легко повторно использовать по отдельности, так что они не обмениваются информацией без необходимости. В последствии, даже зная, что выходной двоичный формат имеет ORG 0 (и секция .text будет начинаться с 0), эта информация не поступит назад к оценщику выражений. Так что, с точки зрения оценщика, $ — не просто число, а адрес, включающий смещение от базы (основы) сегмента. Поэтому разница между $ и 510 тоже будет включать значение смещения от базы сегмента (0х1234:0х5678 вместо 0х5678, например). Значение, включающее смещение, нельзя передавать в качестве параметра директиве TIMES.

Решение можно увидеть в предыдущем примере:

TIMES 510-($-$$) DB 0

Здесь $ и $$ содержат смещения относительно одного и того же сегмента, так что их разница — простое число. Это решит проблему и будет сгенерирован правильный код.

10.2 Дефекты (ошибки)

Мы пока еще не выпускали ни одной версии NASM с дефектами, о которых мы знаем. Хотя это и не исключает наличия множества таких дефектов, о которых мы просто не знаем. О любом, найденном вами, вы должны сообщить по адресу hpa@zytor.com.

Прежде чем сообщать о дефекте, пожалуйста, внимательно прочитайте параграф 2.2, там перечислены преднамеренно созданные особенности, которые можно принять за ошибки в NASM. (Если же что-то не описано там и кажется вам ошибкой, то будем рады получить ваши подробные комментарии, а не просто письмо типа "Это - ошибка"). После этого прочитайте параграф 10.1, и не сообщайте об ошибке, если она уже там описана.

Если вы создаете отчет об ошибке, пожалуйста, сообщите нам всю нижеследующую информацию: