7. Команды перехода 7.1. Команда сравнения

Лекции по предмету «Информатика»
Информация о работе
  • Тема: 7. Команды перехода 7.1. Команда сравнения
  • Количество скачиваний: 3
  • Тип: Лекции
  • Предмет: Информатика
  • Количество страниц: 12
  • Язык работы: Русский язык
  • Дата загрузки: 2014-05-05 15:31:26
  • Размер файла: 43.29 кб
Помогла работа? Поделись ссылкой
Ссылка на страницу (выберите нужный вариант)
  • 7. Команды перехода 7.1. Команда сравнения [Электронный ресурс]. – URL: https://www.sesiya.ru/lekcii/informatika/7-komandy-perehoda--71-komanda-sravneniya/ (дата обращения: 12.04.2021).
  • 7. Команды перехода 7.1. Команда сравнения // https://www.sesiya.ru/lekcii/informatika/7-komandy-perehoda--71-komanda-sravneniya/.
Есть ненужная работа?

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

добавить работу
Обратиться за помощью в подготовке работы

Заполнение формы не обязывает Вас к заказу

Информация о документе

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

Если Вы являетесь автором текста представленного на данной странице и не хотите чтобы он был размешён на нашем сайте напишите об этом перейдя по ссылке: «Правообладателям»

Можно ли скачать документ с работой

Да, скачать документ можно бесплатно, без регистрации перейдя по ссылке:

7. Команды перехода
7.1. Команда сравнения
Сначала рассмотрим команду, тесно примыкающую к группе арифметических команд.
Сравнить cmp opr1,opr2 opr1 – opr2
CoMPare two operands — сравнить два операнда меняет все флаги состояния
cmp r/m8,i8; r/m16,i16; r/m16,i8; r/m8,r8; r/m16,r16; r8,r/m8; r16,r/m16
Ограничение: opr1 не может быть непосредственным операндом (т.е. команда cmp 2,bx недопустима).
Команда cmp аналогична команде вычитания, но результат вычитания нигде не запоминается! Зачем нужна такая команда? Здесь важны флаги как результат операции вычитания. Не изменяя операндов, можно по флагам выяснить совпадают ли операнды, какой из них больше и т.д. Например, если AX = BX, то после выполнения команды cmp¬ ax,bx флаг ZF установлен. Мы изучим специальную группу команд — команды условного перехода, которые в зависимости от состояния регистра флагов будут вынуждать выполнение разных последовательностей команд.
А теперь зададим простой вопрос: пусть AL = FF, BL = 0, какое из чисел: FF или 0 больше? Ответ неоднозначен:
• если числа знаковые, то BL > AL (т.к. FF = –1),
• если беззнаковые, то AL > BL.
Убедимся в этом, набрав в TD программу:
mov al,ff
mov bl,0
cmp bl,al
Проанализируем флаги (сведем этот анализ в таблицу 7.1).
Таблица 7.1.
Знаковые операнды Беззнаковые операнды
NV PL NZ CY
OF = 0 SF = 0 ZF = 0 CF = 1
переполнения нет BL – AL 0 BL – AL 0 потребовался заем
BL > AL BL < AL

Для знаковых операндов мы проанализировали состояние трех флагов: OF, SF и ZF, для беззнаковых — один флаг CF.
Упражнение. Выполнить в TD программу по шагам. Выписывать на каждом шаге значения флагов. Интерпретировать их.
mov ax, FEFE
mov bx, FFFD
cmp al,ah
cmp al,bh
cmp al,bl
cmp bh,al
cmp bl,al

7.2. Пример команды условного перехода
До сих пор мы изучали команды, на основе которых можно писать так называемые линейные программы, т.е. программы, где порядок выполнения инструкций неизменен. Но даже при программировании формул мы ощущали, что при возникновении, допустим, знакового переполнения лучше прервать вычисления и сообщить об этом пользователю. Для того чтобы это реализовать, нам нужны команды, которые анализируют регистр флагов и в зависимости от состояния флагов осуществляют ветвление. В процессорах семейства 80x86 для этого предназначена большая группа команд — команды условного перехода.
Сначала детально разберем одну из этих команд, а потом рассмотрим всю их совокупность.
Команда jz (Jump if Zero — переход, если результат нулевой) проверяет состояние флага ZF. Если ZF установлен (т.е. ZF = 1), то совершается переход; если ZF сброшен (ZF = 0), то выполняется команда, следующая за командой перехода. Рассмотрим программный фрагмент:
cmp ax,1 ; AX – 1 = 0 ?
jz n ; ДА — переход на метку n
inc cx ; НЕТ — увеличить счетчик
n: nop
Команда jz проверяет только равенство содержимого AX единице, она не проверяет, допустим, верно ли, что AX > 1, это осуществляют другие команды, анализирующие соответствующие комбинации флажков. Проверяется только состояние ZF. Если AX = 1, то ZF = 1 и происходит переход на метку n. Если AX не равно 1, то команда перехода пропускается и выполняется команда inc cx. Команда jz имеет альтернативную мнемонику je (Jump if Equal — переход, если равно). И та и другая мнемоники при трансляции порождают одинаковый машинный код; программист использует более понятную для читателя программы мнемонику: в нашем примере проверяется совпадение содержимого AX и BX, поэтому уместнее было написать je ax,bx.
Код команды перехода занимает два байта:
КОП Data8
Первый байт — код операции. Для jz/je это 74h. Во втором байте — 8-разрядное смещение относительно текущего значения IP. В момент выполнения команды IP содержит адрес следующей команды, в нашем примере — адрес команды inc cx. Если проверяемое условие выполнено (т.е. в нашем случае ZF = 1), то смещение расширяется со знаком до слова и прибавляется к IP.
Смещение — знаковое число. Положительное смещение соответствует переходу вперед, к старшим адресам, отрицательное — назад, к младшим адресам. Поэтому смещение во втором байте указывается в дополнительном коде. Диапазон переходов: 128 байт назад, 127 байт вперед (относительно адреса команды, следующей за командой перехода). А если нужно перейти на более далекое расстояние? Для этого придется дополнительно привлечь команды безусловного перехода, которые мы изучим позднее (переход внутри сегмента и межсегментный переход).
Теперь изучим коды команд приведенного выше примера (табл. 7.2).

Таблица 7.2.
Исходный
фрагмент Адрес
(смещение) Код Мнемоника
в debug
cmp ax,1 0300 390100 CMP AX,1
jz n 0303 7401 JZ 306
inc cx 0305 41 INC CX
n: nop 0306 90 NOP

В момент выполнения команды jz n счетчик команд IP = 0305 (адрес следующей инструкции). Если AX = 1, то к IP прибавляется смещение (01), расширенное со знаком до слова (0001). Если AX отлично от 1, то IP не изменяется, поэтому выполняется команда, следующая за командой перехода.
В правой колонке таблицы приведен фрагмент программы, набранный в TD. В TD метки использовать нельзя. Ведь мини-ассемблер транслирует команду немедленно при нажатии пользователем клавиши Enter. И он не может предвидеть, какие команды будут введены далее. Поэтому адрес назначения для команды перехода в TD следует указывать непосредственно (фактически вводится числовое значение метки). Зато ассемблеры MASM и TASM получают на входе текст программы и поэтому могут рассчитать расстояние от команды перехода до метки, на которую совершается переход.
Команда jz/je имеет своего двойника — команду jnz/jne (Jump if not zero/not equal — переход если не нуль/не равно). Эта команда проверяет, сброшен ли флаг ZF (ZF = 0), и если это условие выполняется, то осуществляет переход.
Упражнение. Наберите в TD программу (программа вычисляет сумму 6+5+4+3+2+1)
XXXX:0100 mov ax,0
XXXX:0103 mov cx,6
XXXX:0106 add ax,cx
XXXX:0108 dec cx
XXXX:0109 jne 106
XXXX:010B nop
Вручную рассчитайте содержимое байта смещения в команде jne 106, затем проведите ее дисассемблирование и сверьте с вашим ответом.

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

7.3. Простые переходы
Эти команды представлены в табл. 7.3.

Таблица 7.3. Простые переходы
Флаг Значение Мнемоника Комментарий
флага команды
ZF 1 jz/je zero — нуль, equal — равно
0 jnz/jne
SF 1 js sign — знак
0 jns
OF 1 jo overflow — знаковое переполнение
0 jno
PF 1 jp/jpe parity even — четный паритет
0 jnp/jpo parity odd — нечетный паритет
CF 1 jc/(jnae/jb) carry — перенос
0 jnc/(jae/jnb)

Итак, анализируются все флаги состояния (кроме AF, но как мы помним, на него возложены специальные функции — он нужен только для команд десятичной коррекции). Флаги управления не анализируются, так как они устанавливаются и сбрасываются не по результатам операций, а специальными командами. Для пяти флагов состояния имеется десять команд перехода. Половина совершает переход, если флаг установлен, половина — если сброшен. Для команд jc и jnc имеются альтернативные мнемоники из группы беззнаковых переходов.
Задача*. Для получения абсолютной величины содержимого регистра AX иногда используют следующее «остроумное» решение:
p: neg ax
js p
Объясните, чем опасен этот фрагмент.
Решение. При AX = 8000h происходит зацикливание.

7.4. Беззнаковые и знаковые переходы.
Эта группа команд обычно используется после команды сравнения cmp для выяснения вопроса, какое из двух чисел больше. При этом числа рассматриваются как беззнаковые. Вспомним, что команда cmp opr1,opr2 вычисляет разность opr1 – opr2 и (не запоминая результата) выставляет флаги. При этом opr1 – opr2 < 0 эквивалентно opr1 < opr2. Чтобы отличить беззнаковые отношения от знаковых, используется специфическая терминология (табл. 7.4.).

Таблица 7.4.
Отношение Беззнаковые Знаковые
> выше (above) больше (greater)
< ниже (below) меньше (less)

Беззнаковые переходы представлены в табл. 7.5.

Таблица 7.5. Беззнаковые переходы.
Отношение Переход,если …
(Jump if …) Мнемоника Проверяемое
условие
< ниже/не (выше или равно)
below/not above nor equal jb/jnae CF = 1

выше или равно/не ниже
above or equal/not below jae/jnb CF = 0

ниже или равно/не выше
below or equal/not above jbe/jna CF ZF = 1

> выше/не (ниже или равно)
above/not below nor equal ja/jnbe CF ZF = 0


Рассмотрим первую команду: при вычитании opr2 из opr1 потребовался заем, поэтому CF = 1. Но это означает, что opr1 < opr2. В третьей команде проверяется дизъюнкция флагов CF и ZF, т.е. допускается и отношение "ниже" и равенство.
Первые две команды нам встретились среди простых переходов. Альтернативные мнемоники введены для лучшей читабельности программы. Ассемблер сгенерирует одинаковый код независимо от мнемоники.
Беззнаковые переходы, как правило, применяются при сравнении адресов (смещений) внутри сегмента. Использование для этой же цели знаковых переходов является грубой и трудно выявляемой ошибкой (т.к. в определенном диапазоне операндов знаковые и беззнаковые переходы будут осуществляться одинаково).
Знаковые переходы представлены в табл. 7.6.

Таблица 7.6. Знаковые переходы
Отно-
шение Переход,если …
(Jump if …) Мнемоника Проверяемое
условие
< меньше/не больше или равно
less/not greater nor equal jl/jnge


больше или равно/не меньше
greater or equal/not less jge/jnl


меньше или равно/не больше
less or equal/not greater jle/jng

> больше/не (меньше или равно)
greater/not less nor equal jg/jnle


Здесь операция означает отрицание эквивалентности, или сложение по модулю 2. Чтобы разобраться с загадочными комбинациями флагов, рассмотрим программный фрагмент
cmp al,bl
jge m
Что означает ? Это возможно в двух случаях (вспомним таблицу истинности для ). 1) SF = 0 — результат вычитания AL – BL неотрицательный; OF = 0 — знакового переполнения не было (результат в допустимом диапазоне). Тогда AL BL и осуществляется переход на метку m. 2) SF = 1 — результат вычитания AL – BL отрицательный; OF = 1 — имело место знаковое переполнение. Это означает, что на самом деле результат неотрицательный! Тогда AL BL и происходит переход на метку m.
Упражнение. Подобрать значения AL и BL, чтобы проверить сделанные утверждения.
Для команды jg условие еще сложнее. Рассмотрим фрагмент:
cmp al,bl
jg m
Пусть AL = BL. После вычитания BL из AL флаг ZF установлен (ZF = 1). Переход не выполняется. Пусть теперь AL BL. Тогда ZF=0. Мы свели рассмотрение к уже разобранной команде jge.
Из этих рассмотрений следует важный вывод: даже если при выполнении команды cmp возникает переполнение, команды условного перехода работают правильно. Еще один вывод: для каждой команды условного перехода Jcc (JNcc) имеется дополнительная команда JNcc (Jcc), которая проверяет противоположное условие. Достаточно в мнемонике команды добавить букву N (если ее нет) или снять ее.

7.5. Команды безусловного перехода
К только что рассмотренным командам условного перехода тесно примыкает команда:
короткий переход jmp short opr IP IP + Data8

short — короткий флаги не изменяются
Код этой команды занимает два байта:
EBh Data8
Первый байт — код операции. Во втором байте — 8-разрядное смещение относительно текущего значения IP. Механизм действия такой же, как у команд условного перехода, только прибавление к IP смещения Data8 происходит всегда, независимо от состояния флагов.
Для перемещения в пределах сегмента предназначена команда:
ближний переход jmp near opr IP IP + Data16

near — ближний флаги не изменяются
Для межсегментных перемещений нужна команда:
дальний переход jmp far opr IP offset opr
CS segment opr

far — дальний флаги не изменяются
short, near, far — атрибутные операторы, которые помогают Ассемблеру сгенерировать правильный код команды перехода. Позднее мы увидим, что TASM предоставляет специальную директиву (JUMPS), которая позволяет не указывать атрибутный оператор.
Введем в TD две инструкции перехода и проанализируем их код:
cs:0100 EB1E jmp 0120
cs:0102 E9FB00 jmp 0200
Мы обошлись без указания атрибутного оператора, т.к. отладчик сам мог определить тип используемой команды перехода.
Первая инструкция была воспринята как команда короткого безусловного перехода. Ее код занимает два байта. Data8 = 1Eh. Содержимое IP плюс смещение: 0102h + 001Eh = 0120h.
Для второй инструкции "длина прыжка" превышает 127, и TD сгенерировал команду ближнего перехода. Ее код занимает три байта. Data16 = 00FBh. Тогда 0105h + 00FBh = 0200h.
Теперь можно построить условный переход на адрес в текущем сегменте, расстояние до которого превышает 127.
cs:0100 3D0000 cmp ax,0000
cs:0103 7503 jne 0108 ;Проверка противоположного условия
cs:0105 E9F800 jmp 0200 ; ближний переход, если противоположное
cs:0108 90 nop ; условие не удовлетворяется)
Хотелось бы еще посмотреть код для команды дальнего перехода, например, jmp far 2000:0120. Но TD почему-то не воспринимает эту команду при ее вводе (выдает сообщение: Invalid operand(s) — неверный операнд). Поэтому введем код этой команды в панели данных. Из справочника [Юров, с.90] выясняем, что код этой команды EA. Подумаем, как ввести непосредственный операнд. Более значимое (сегментная часть адреса перехода) должна хранится по более старшему адресу, поэтому код должен формироваться так:
EA offset segment
т.е. в нашем случае так:
EA 0120 2000
Слова в коде команды надо представить как последовательность байтов, помня о перевернутом порядке их расположения:
EA 20 01 00 20
В панели данных перейдем на адрес 100 (Ctrl+G) и введем (Ctrl+C) последовательность байтов:
0EA,20,1,0,20
В панели команд мы увидим:
cs:0100 EA20010020 jmp 2000:0120

7.6. Структурное программирование условного оператора.
На псевдокоде условный оператор выглядит так:
если условие то действие_1 иначе действие_2
Условие может принимать значения ИСТИНА и ЛОЖЬ. В первом случае выполняется последовательность команд действие_1, во втором — действие_2.
Хотелось бы и в программе на языке Ассемблера сохранить очередность действий, как на псевдокоде. Рекомендуется такая схема:
CMP A1,A2 ; A1 – A2 rel 0 ; (rel — отношение >,<,= и т.д.)
JNrel m
действие_1
JMP cont
m: действие_2
cont: NOP
Например, если проверяется равенство операндов, то команда перехода — jne, если же, напротив, проверяется неравенство, то используется je (два отрицания N как бы уничтожают друг друга). Теперь мы видим, насколько полезны альтернативные мнемоники с проверкой отрицательного условия. Они позволяют писать программы, следуя определенной дисциплине, что делает текст программы более понятным для человека.

7.7. Использование команд перехода в TD
В зависимости от содержимого регистра флагов команды перехода изменяют содержимое программного счетчика IP. Для этого в команде перехода закодировано относительное смещение, которое процессор прибавляет к содержимому IP, если выполняется условие, для которого предназначена команда перехода. Но мини-ассемблер debug неспособен предвидеть, какие команды будет вводить пользователь, поэтому он не в состоянии рассчитать смещение в команде перехода (в отличие от Ассемблера, который анализирует весь текст программы). Поэтому пользователь должен указывать адрес назначения, а если он неизвестен и пользователю, то сначала набирать фиктивный адрес назначения, а затем корректировать его. Поясним это на примере.
Напишем программный фрагмент, который меняет содержимое аккумулятора AX по следующему правилу:
при AX 0 AX := 1, при AX < 0 AX := –1,
т.е. фактически реализует знаковую функцию sign(x). С использованием нотации языков программирования высокого уровня это можно записать так:
ЕСЛИ AX >= 0 ТО AX := 1 ИНАЧЕ AX := –1.
Составляем текст программы:
cmp ax,0 ; Установить флаги по результату: AX – 0
jnge m ; Если условие AX >= 0 не выполняется, то переход
; на альтернативное действие
mov ax,1
jmp c ; Обход альтернативного действия
m: mov ax,–1
c: nop

Обратите внимание, что команда перехода содержит мнемонику отрицания (n — Not) условия (ge — Greater or Equal — больше или равно). Тем самым порядок основного и альтернативного действия такой же, как в операторе на псевдокоде.
Набираем программу в отладчике.
cmp ax,0
jnge 100 (пока адрес неизвестен)
mov ax,1
jmp 100 (пока адрес неизвестен)
mov ax,-1
nop

Получаем:
cs:0100►3D0000 cmp ax,0000
cs:0103 7CFB jl 0100
cs:0105 B80100 mov ax,0001
cs:0108 EBF6 jmp 0100
cs:010A B8FFFF mov ax,FFFF
cs:010D 90 nop
Теперь адреса известны (m = 010Ah, c = 010Dh) и можно заново ввести команды перехода: по адресу 103 команду jnge 10a, по адресу 105 команду jmp 10dh. Окончательно код выглядит так:
cs:0100►3D0000 cmp ax,0000
cs:0103 7C05 jl 010A
cs:0105 B80100 mov ax,0001
cs:0108 EB03 jmp 010D
cs:010A B8FFFF mov ax,FFFF
cs:010D 90 nop
Обратите внимание, что во второй строке появилась альтернативная мнемоника команды перехода (не jnge, а jl). Проанализируем код команд перехода. Рассмотрим первую из команд. Ее машинный код 7C05: 7C — код операции, 05 — относительное смещение. В момент выполнения команды IP = 0105h, т.е. IP содержит адрес следующей команды. Если условие команды перехода выполнено, то IP  IP + 05 = 0105h + 0005h = 010Ah, т.е. значение метки m.
Протестируйте эту программу при различных исходных данных.

7.8. Пример программы, включающей условные переходы (задание A3).
7.8.1. Формулировка задания
Дана строка из двух десятичных цифр. Если сумма цифр больше 10, то поменять цифры местами, иначе — уменьшить первую цифру на три, если это возможно. Указать набор тестов. Проанализировать код одной из команд условного перехода.
Отчет должен содержать: текст программы с комментариями, набор тестов, результат анализа кода одной из команд условного перехода.

5.9.2. Алгоритм и программа
Алгоритм решения задач на псевдокоде выглядит так:
если сумма цифр > 10
то поменять цифры местами
иначе
если первая цифра >= 3
то уменьшить первую цифру на три

Детализируем алгоритм с учетом представления цифр в коде ASCII (код цифры = 30h + цифра).
дано d1, d2 коды цифр
если d1+d2 > 0Ah + 30h + 30h
то d1,d2 := d2,d1
иначе
если d1 >= 3 + 30h
то d1 := d1 – 3

Осуществим программную реализацию алгоритма. Код первой цифры разместим в байте по адресу 200, а код второй — по адресу 201. Сразу же поместим эти коды в регистры, чтобы увеличить быстродействие программы. Текст программы:
mov al,[200] ; Первая цифра — в AL.
mov ah,[201] ; Вторая цифра — в AH.
add al,ah ; Сумма кодов цифр — в AL.
cmp al,6a ; Сравниваем сумму кодов с числом 10 с
; учетом "лишних" слагаемых 30h.
jng m ; Если сумма больше 10,
xchg ah,[200] ; то меняем местами
mov [201],ah ; цифры,
jmp fin
m: sub al,ah ; иначе восстанавливаем код первой цифры.
cmp al,33 ; Будет ли в AL код цифры после вычитания 3?
jnge fin ; Если ДА,
sub al,3 ; то вычитаем из кода цифры тройку mov [200],al ; и возвращаем цифру в память
fin: nop
Первые две команды можно было объединить в одну: mov ax,[200], но для наглядности оставлен более громоздкий вариант.
Комментарии не являются словесным описанием команды, а раскрывают ее смысл в программе. Например, к третьей команде можно было дать такой "комментарий":
add al,ah ; сложить AL и AH и поместить сумму в AL.
но он ничего не скажет читателю, зачем эта команда помещена в программу. Строку комментария начинаем с прописной буквы. Если фраза комментария занимает несколько строк, то с прописной буквы начинаем только первую строку.
В программу следовало еще включить проверку, что обрабатываемая строка действительно является строкой цифр, т.е. каждый код заключен в диапазоне [30h, 39h]. Но с учетом учебного характера программы это не сделано.
Составим набор тестов (табл.7.7). Тесты нужно выбирать так, чтобы при прогоне программы на тестах была пройдена каждая "веточка" алгоритма. Кроме того, с учетом известной ошибки следует выбирать тесты, дающие при выполнении "граничные значения". В нашем примере, следует взять набор из двух цифр, дающих в сумме 10, чтобы проверить правильность кодировки условия.
Таблица 7.7. Набор тестов
До Условие Действие После
68 6 + 8 = 14 > 10 переставить цифры 86
37 3 + 7 =10 10, 3 3
уменьшить первую цифру на 3 07
24 2 + 4 = 6 <= 10, 2 < 3 нет 24

7.8.3. Реализация программы в TD.
Сначала введем текст программы. Каждая команда после нажатия Enter преобразуется в машинный код. Имеется особенность: нельзя ввести инструкцию jng m. Вместо метки m нужно вводить конкретный адрес команды, на которую планируется переход. Но так как команду с этой меткой еще только предстоит ввести, ее адрес нам неизвестен ("ссылка вперед"). Поэтому введем jng 100, а после ввода всей программы, откорректируем адреса в командах перехода.
mov al,[200]
mov ah,[201]
add al,ah
cmp al,6a
jng 100 (пока адрес неизвестен)
xchg ah,[200]
mov [201],ah
jmp 100 (пока адрес неизвестен)
sub al,ah
cmp al,33
jnge 100 (пока адрес неизвестен)
sub al,3
mov [200],al
nop

Теперь нам стало известно, что метке m соответствует адрес (смещение) 117, а метке fin — адрес 122. Исправим команды перехода. По адресу 10b введем jng 117, по адресу 115 введем jmp 122, по адресу 11B введем jnge 122.
А посмотрим дисассемблированный текст программы:
cs:0100 A00002 MOV AL,[0200]
cs:0103 8A260102 MOV AH,[0201]
cs:0107 00E0 ADD AL,AH
cs:0109 3C6A CMP AL,6A
cs:010B 7E0A JLE 0117
cs:010D 86260002 XCHG AH,[0200]
cs:0111 88260102 MOV [0201],AH
cs:0115 EB0B JMP 0122
cs:0117 28E0 SUB AL,AH
cs:0119 3C33 CMP AL,33
cs:011B 7C05 JL 0122
cs:011D 2C03 SUB AL,03
cs:011F A20002 MOV [0200],AL
cs:0122 90 NOP
Команда jng 117 превратилась в jle 117, а команда jnge 122 — в jl 122. Ошибки нет! Для команд условного перехода отладчик выбрал альтернативную мнемонику.
Сохраним программный код в файле a3v0.com.
Протестируем программу. Проделаем последовательность действий. Введем тестовую строку, начиная с 200-го адреса. Для этого в панели данных перейдем к адресу 200 (Ctrl+G) и осуществим ввод строки "68" (Ctrl+C). Выполним прогон программы с 100-го адреса до адреса, соответствующего метке fin (т.е. 0122). Для этого поставим курсор на метку 0122 и нажмем F4. Посмотрим дамп памяти — два байта по адресу 200. Отображается:
ds:0200 38 36 86
Вводим новые исходные данные — строку "37". Устанавливаем курсор в панели кода на адрес cs:0100, нажимаем Ctrl+N. Всё подготовлено ко второму прогону программы.
Все три теста выполнены правильно. Если бы результат не соответствовал ожиданиям, то следовало бы предпринять трассировку программы "по шагам", тщательно анализируя результат выполнения каждой команды.
Проанализируем код команды jle 117. Рассмотрим фрагмент программы.
157A:010B 7E0A JLE 0117
157A:010D 86260002 XCHG AH,[0200]
В коде команды 7E0A: 7E — код операции jle, а 0A — смещение. Смещение прибавляется к числу 10D – адресу следующей команды (Именно это число хранится в регистре IP в момент выполнения команды перехода). 010Dh + 000Ah = 100h + 13 +10 = 100h + 23= 100h + 16 + 7 =100h + 10h + 7h = 117h, т.е. адрес, соответствующий метке m.
Отметим типичную ошибку при решении этой задачи. В условии задачи речь идет о строке из двух цифр. Но вместо цифр по адресу 200 вводят соответствующие им числа: 6, 8. Отображается:
ds:0200 06 08 ♠◘
Справа отображаются не цифры!

Завершим работу в отладчике: Alt+X.