Иллюстрированный самоучитель по Assembler

Циклы и условные переходы

В приведенном выше фрагменте внешний цикл выполняется 2000 раз; внутренний – 65536 раз. При счете числа шагов внутреннего цикла используется явление оборачивания, которое уже упоминалось ранее. Начальное значение в регистре СХ равно нулю; после выполнения тела цикла 1 раз команда loop уменьшает содержимое СХ на 1, что дает число FFFFh (которое можно рассматривать, как -1). В результате цикл повторяется еще 65535 раз, а в сумме – точно 64К шагов.

Команда loop внутреннего цикла передает управление на саму себя, т.е. тело внутреннего цикла состоит из единственной команды loop. В этом нет ничего незаконного. Любая команда, в том числе и loop, требует какого-то времени для своего выполнения, и повторение 64 К раз команды loop дает некоторую временную задержку (на современных процессорах порядка тысячной доли секунды).

Перейдем теперь к рассмотрению команд условных переходов.

В приведенном выше фрагменте для реализации длинного цикла использовалась команда условного перехода по равенству je. В системе команд МП 86 имеется свыше трех десятков команд условных переходов, позволяющих осуществлять переходы при наличии разнообразных условий: равенства, неравенства, положительности или отрицательности результата и проч. При выполнении всех этих команд процессор анализирует содержимое регистра флагов и осуществляет (или не осуществляет) переход на указанную метку в зависимости от состояния отдельных флагов или их комбинаций.

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

cmp AX,BX; Сравнение двух регистров
je equal; Переход, если AX=BX
cmp SI,mem; Сравнение регистра и ячейки памяти
jne notequ; Переход, если SI<>mem
int 21h; Вызов DOS
jc syserr; Переход, если была ошибка
;и флаг CF=1
or BX,BX; Анализ BX
jz zero; Переход, если BX=0
inpt: in AL,DX; Ввод данного из устройства
test AL,80h; Анализ бита 7 в данном
je inpt; Ввод до тех пор, пока
;бит 7=0 (ожидание установки бита 7)
test AX,7; Анализ битов 0.1.2 в AX
jne found; Переход, если хотя бы 1 бит
;из них установлен
test DI,OFh; Анализ битов 0…3 в DI
jz reset; Переход, если все они сброшены

В гл. 2 отмечалось, что двоичные числа, записываемые в регистры процессора или ячейки памяти, можно рассматривать, либо как числа существенно положительные, т.е. числа без знака, либо как числа со знаком. Например, адреса ячеек, разумеется, не могут быть отрицательными. Поэтому число FFFFh, если по смыслу программы оно является адресом, обозначает 65535. Если, однако, то же число FFFFh получилось в арифметической операции вычитания 2 из 1, то его надо рассматривать, как – 1. Точно так же понятие знака бессмысленно по отношению к кодам символов, которые с равным успехом могут принимать любое значение из диапазона 0…255. С другой стороны, мы можем условно считать, что коды символов первой половины таблицы ASCII положительны, а коды второй половины таблицы (у них установлен старший бит) отрицательны, и использовать для обработки символов команды, чувствительные к знаку.

В составе команд условных переходов имеются две группы команд для сравнения чисел без знака (это команды ja, jae, jb, jbc, jna, jnae, jnb и jnbe) и чисел со знаком (jg, jge, jl, jle, jng, jnge, jnl и jnle). В аббревиатурах этих команд для сравнения чисел без знака используются слова above (выше) и below (ниже), а для чисел со знаком – слова greater (больше) и less (меньше).

Разница между теми и другими командами условных переходов заключается в том, что команды для чисел со знаком рассматривают понятия "больше- меньше" применительно к числовой оси – 32К…0…+32К, а команды для чисел без знака – применительно к числовой оси 0…64К. Поэтому для первых команд число 7FFFh (+32767) больше числа S000h (-32768), а для вторых число 7FFFh (32767) меньше числа S000h (32768). Аналогично, команды для чисел со знаком считают, что 0 больше, чем FFFFh (-1), а команды для чисел без знака – меньше.

Рассмотрим пример использования команд условных переходов для обработки символов. Пусть мы вводим с клавиатуры некоторую строку символов (например, имя файла), и хотим, чтобы в программе эта строка была записана прописными буквами, независимо от того, какие буквы использовались при ее вводе.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.