 |
mov ax,bx
которая означает "поместить AX в BX", читается слева направо, и
многие создатели микропроцессоров строят соответствующим образом
свои ассемблеры. Однако в языке Ассемблера процессора 8086 фирма
Intel использовала другой подход, поэтому для нас эта строка оз-
начает "поместить BX в AX", что иногда приводит к путанице.
Программист забывает о стеке или резервирует маленький стек
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
В большинстве случаев не выделять явно пространство для сте-
ка, это все равно, что ходить по тонкому льду. Иногда программы,
TDeb 3.0 #2-3 = 140 =
в которых не выделяется пространство для стека, будут работать,
поскольку может оказаться так, что назначенный по умолчанию стек
попадет в неиспользуемую область памяти. Но нет никакой гарантии,
что такие программы будут работать при любых обстоятельствах,
поскольку нет гарантии, что для стека будет доступен по крайней
мере один байт. В большинстве программ для резервирования прост-
ранства для стека должна присутствовать директива .STACK, и для
любой программы эта директива должна резервировать достаточное
пространство, чтобы его хватило для максимальных потребностей в
программе.
Вызов подпрограммы, которая портит содержимое нужных регистров
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
При разработке программы на Ассемблере регистры удобно расс-
матривать, как локальные переменные, выделенные для использования
в процедуре, с которой вы в данный момент работаете. В частности,
нередко подразумевают, что при обращении к другим процедурам ре-
гистры остаются неизмененными. На самом деле это не всегда так.
Регистры - это глобальные переменные, и каждая процедура может
сохранить или уничтожить содержимое любого из регистров.
Ошибки при использовании условных переходов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Использование в языке Ассемблера инструкций условных перехо-
дов (JE, JNE, JC, JNC, JA, JB, JG и т.д) обеспечивает большую
гибкость в программировании, но при этом также очень просто оши-
биться, выбрав неверный переход. Кроме того, поскольку в языке
Ассемблера анализ условия и переход требуют по крайней меру двух
строк исходного кода (а сложных условных переходов нескольких
строк), условные переходы в языке Ассемблера менее очевидны и
больше способствуют ошибкам, чем соответствующие операторы Паска-
ля и Си.
Неверное понимание работы префикса REP
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Команды обработки строк имеют одну необычную особенность:
после их выполнения используемые ими указатели сдвигаются таким
образом, что указывают на адрес, отличающийся на 1 байт (или 2
байта, если если длина команды равна одному слову) от последнего
обработанного адреса. Это может привести к некоторой путанице при
повторении команд обработки строк, особенно команд REP SCAS и REP
CMPS.
Нулевое содержимое CX и работа с целым сегментом
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Повторное выполнении любых команд обработки строк при ра-
венстве нулю регистра CX не даст никакого результата. Это может
быть удобно в том смысле, что нет необходимости проверять его на
ноль перед повторным выполнением команд обработки строк. С другой
TDeb 3.0 #2-3 = 141 =
стороны, невозможно получить доступ к каждому байту в сегменте с
помощью байтовых команд обработки строк.
Неправильная установка флага направления
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
При выполнении команды обработки строк связанные с ней ука-
затели (SI, DI или оба) получают положительное или отрицательное
приращение. Это зависит от состояния флага направления.
С помощью команды CLD флаг направления может быть сброшен в
0. В этом случае при выполнении команд обработки строк указатель
получает положительное приращение (смещается в сторону старших
адресов). С помощью команды STD флаг направления устанавливается
в 1. В этом случае указатель получает отрицательное приращение
(сдвигается в сторону младших адресов). После того, как флаг нап-
равления был установлен в определенное состояние, он будет оста-
ваться в нем до тех пор, пока не будет выполнена еще одна команда
CLD или STD, или пока значения флагов не будут извлечены из стека
с помощью команды POPF или IRET. С одной стороны, удобно иметь
возможность устанавливать флаг направления в определенное состоя-
ние только один раз, а затем выполнять серию команд, которые
должны использовать заданное направление. С другой стороны, это
может привести к появлению неустойчивых и труднообнаруживаемых
ошибок, в результате которых команды обработки строк работают по-
разному в зависимости от работы команд, которые были выполнены
значительно раньше.
Ошибки при повторении команд сравнения строк
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Команда CMPS сравнивает содержимое двух областей памяти, а
команда SCAS сравнивает содержимое накапливающего регистра с со-
держимым области памяти. Когда перед одной из этих команд стоит
префикс REPE, она выполняет сравнение, либо пока CX не становится
равным нулю, либо пока не обнаружится, что операнды не равны.
Когда перед командой стоит префикс REPNE, она выполняет сравне-
ние, либо пока CX не становится равным нулю, либо пока не обнару-
жится что операнды равны. К несчастью, легко перепутать, где ка-
кой префикс нужно использовать.
Ошибки при назначении сегмента строк
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Все строковые команды по умолчанию используют в качестве
сегмента исходных данных (если он есть) сегмент DS, а в качестве
сегмента результирующих данных (если он есть) сегмент ES. Легко
забыть об этом и попытаться, скажем, выполнить команду STOSB над
сегментом данных, поскольку все данные, обрабатываемые не строко-
выми командами, обычно находятся именно в этом сегменте.
Неправильное преобразование из байта в слово
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
TDeb 3.0 #2-3 = 142 =
В общем случае, для команд обработки строк желательно ис-
пользовать максимально возможный размер данных (обычно слово, а
для процессора 80386 - двойное слово), поскольку с данными боль-
шего размера эти команды обычно работают быстрее.
Однако здесь имеются две ловушки. Во-первых, преобразование
из количества байт в количество слов с помощью простой команды:
shr cx,l
приведет к потере байта, если CX имеет нечетное значение, пос-
кольку младший значащий бит будет сдвинут за пределы слова.
Во-вторых, следует помнить, что команда SHR делит количество
байт на два. Использование, скажем, команды STOSW с количеством
байт, а не слов, может уничтожить другие данные и вызвать самые
разнообразные ошибки.
Использование нескольких префиксов
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Команды обработки строк с несколькими префиксами работают
ненадежно, и их следует по возможности избегать.
Необязательные операнды в командах обработки строк
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Необязательные операнды в командах обработки строк использу-
ются только для задания размера данных и изменения сегмента и не
гарантируют фактический доступ к данной области памяти.
Уничтожение содержимого регистра при умножении
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Умножение (8 на 8 бит, 16 на 16 бит, либо 32 на 32 бита)
всегда уничтожает содержимое как минимум одного регистра, не яв-
ляющегося накапливающим регистром, который используется в качест-
ве исходного операнда.
TDeb 3.0 #2-3 = 143 =
Ошибки, связанные с изменением содержимого регистров
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Команды обработки строк, такие как MOVS, STOS, LODS, CMPS и
SCAS, могут влиять на состояние некоторых флагов и содержимое
трех регистров при выполнении единственной команды. При использо-
вании команд обработки строк следует помнить, что содержимое од-
ного из регистров SI или DI (или обоих сразу) получает положи-
тельное или отрицательное приращение (в зависимости от состояния
флага направления) при каждом выполнении команды обработки строк.
Содержимое регистра CX также получает отрицательное приращение
как минимум один раз и, возможно, уменьшается до нуля при каждом
использовании команды обработки строк с префиксом REP.
Изменение состояния флага переноса
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
В то время как одни команды неожиданно для программиста вли-
яют на состояние регистров и флагов, другие команды не влияют да-
же на те флаги, состояние которых было бы желательно изменить.
Программист долго не использует флаги
ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
Состояние флагов сохраняется до тех пор, пока не будет вы-
полнена следующая команда, которая его изменяет, что обычно про-
исходит достаточно быстро. Поэтому рекомендуется после установки
|