Операторы условного и безусловного перехода
Операторы условного и безусловного перехода.
Условный оператор (полная и сокращенная форма)
Форма организации действий, при которой в зависимости от выполнения некоторого условия совершается одна или другая последовательность действий, называется ветвлением. Для организации разветвления вычислительного процесса предназначен оператор условного перехода.
полное ветвление не полное ветвление
Формат оператора:
IF <Условие> THEN <N1 или оператор 1>
Если условие, указанное в операторе выполняется, то управление передается строке с номером N1 или оператору 1, иначе — строке с номером N2 или оператору 2 — полная форма.
IF <Условие> THEN <N1 или оператор 1> — сокращенная форма.
Если конструкция ELSE отсутствует и условие, указанное в операторе IF не выполняется, то управление передается следующей за командой строке.
В Бейсике используются следующие знаки отношения между величинами: =, <>, >, <, >=, <=
Оператор безусловного перехода.
Формат оператора: GOTO N, где N – метка строки.
Множественный выбор (SELECT CASE)
SELECT CASE арифметическое или символьное выражение
CASE условие 1
блок команд 1
…………….
[CASE ELSE
блок команд]
END SELECT
В поле операндов каждого оператора CASE надо указать условие в одном из трёх ФОРМАТОВ:
1. CASE константа 1, константа 2, …
2. CASE IS знак отношения константа
3. CASE константа 1 ТО константа 2
В конструкции сначала вычисляется значение выражения, записанного в SELECT CASE. Далее проверяется, удовлетворят ли это значение одному из указанных в CASE условий, если удовлетворяет, то выполняется блок команд, следующий за данным CASE.
Примеры.
Задача№1. Составьте алгоритм попадания точки с координатами (X,Y) в заштрихованную область.
|
|||
Задача 1. 2 + 7*X-11
PRINT “ Y=“, Y
END
Электронный справочник по ИНФОРМАТИКЕ (Автор Панов В.А.)
Оператор условного перехода IF
Это управляющий оператор, осуществляющий условное ветвление по результатам проверки заложенного условия. Выражение в условии может принимать истинное или ложное значение.
Оператор можно применять в различных видах:
- неполном;
- полном;
- структурном.
Для более быстрого осваивания оператора IF рекомендуется повторить тему «Разветвляющиеся алгоритмы», вспомнить и еще раз разобрать условные конструкции в блок-схемах.
Этот оператор является управляющим оператором условного перехода (направление решения зависит от выполнения некоторого условия).
Формат неполного оператора:
IF (условие) THEN (операторы)
— если условие выполняется, тогда выполняются (операторы) после THEN, а затем работает оператор, следующий за IF;
— если условие не выполняется, тогда сразу срабатывает оператор, следующий за IF.
Логика оператора представлена на схеме:
Условие может быть сложным:
A < 1 OR A > 3 — А меньше 1 или А больше 3
B >-1 AND C < 2 – В больше -1 и С меньше 2
Задача-1.
С клавиатуры вводится число А, не равное нулю. Определить, положительное или отрицательное оно.
Формат полного оператора:
IF (условие) THEN (операторы_1) ELSE (операторы_2)
— если условие выполняется, тогда выполняются (операторы_1) после THEN, а затем работает оператор, следующий за IF;
— если условие не выполняется, тогда выполняются (операторы_2) после ELSE, а затем работает оператор, следующий за IF.
Логика оператора представлена на схеме:
Рассмотрим решение Задачи-1 с помощью полного оператора IF:
Структурный оператор IF
При блочной форме, QuickBASIC тестирует первое логическое выражение. Если оно «истина», выполняются операторы блока THEN. Если первое выражение «ложь», оценивается каждое условие ELSEIF. При выполнении такого условия выполняются операторы данного блока. Если ни одно из условий ELSEIF не выполнено (все = «ложь»), выполняются операторы блока ELSE.
Блоки ELSE и ELSEIF могут отсутствовать. В блочную структуру IF можно вставить любое количество условий ELSEIF. Каждый из блоков может также содержать вложенные блочные структуры IF.
Операторы IF, ELSE, ELSEIF и END IF должны быть первыми операторами в строке. Блок должен заканчиваться оператором END IF.
Программы, написанные с использованием блочной формы легче читаются и отлаживаются.
При проверке сложных условий можно использовать и более современную конструкцию
SELECT… END SELECT.
Пример использования блочной формы IF.
Задача-2. Вводится число от 0 до 1000. Определить количество цифр в нем.
Сборка
— как работает инструкция условного перехода с операндом SUB
спросил
Изменено 9 лет, 1 месяц назад
Просмотрено 4к раз
В данный момент я изучаю язык ассемблера, и в книге по ассемблеру Кипа Ирвина он рассказывает об инструкциях условного перехода и приводит следующий пример
Пример 2: мов бх, 1234ч сабвуфер, 1234 ч jne L5 ; прыжок не сделан je L1 ; прыжок сделан Пример 3: мов сх,0FFFFh вкл сх jcxz L2 ; прыжок сделан
Может кто-нибудь объяснить мне, как работает «je L1» в примере 2. Вам не нужно где-то использовать команду cmp.
Что конкретно заставило вас подпрыгнуть, так как в этот момент bx=0;Кроме того, почему в примере 3 был сделан переход. Я думал, что вы увеличиваете cx, однако jcxz проверит, если cx=0?
Любая помощь будет принята с благодарностью.
- сборка
- x86
- masm
- masm32
Нет, вам не нужно нигде использовать команду cmp
. Многие инструкции влияют на флаги (или их подмножество).
sub
особенно «хорош» для этой цели, потому что он влияет на флаги точно так же, как cmp
(единственное различие между sub
и cmp
заключается в том, что sub
записывает результат вычитание до адресата, тогда как cmp
нет).
Помните, что je
на самом деле просто синоним jz
1234h
минус сам по себе, очевидно, равен нулю, поэтому следует установить флаг Z. Во втором примере jcxz
выполняет переход, если cx = 0
, что имеет место. После приращения cx
оно будет равно нулю, потому что раньше было -1.
Поскольку битовый флаг, установленный при сравнении (в данном случае вас интересуют только ZF
) не очищен.
Кстати, вы должны использовать CMP
, а не SUB
.
«Условие» основано на флагах, обычно флаге переноса, нулевом флаге, отрицательном флаге и флаге переполнения. но не все архитектуры процессоров делают это одинаково, хотя большинство из них используют эти четыре флага.
Эти флаги выходят из «alu», и набор инструкций определяет, на какой флаг влияет или не влияет каждая из инструкций. Таким образом, вы должны просмотреть документацию по каждой инструкции, понять, какие флаги и как затронуты, а затем понять, помогает ли это вам или нет.
Вычитание или сравнение (разница обычно в том, что подпрограмма изменяет результирующий регистр или память, тогда как cmp делает все то же самое, что и вычитание, за исключением того, что она не изменяет место назначения) весьма полезна, потому что с помощью одного вычитания вы можете определить, что больше или равно или меньше (и комбинации меньше или равно, больше или равно).
Для случая je или jump, если они равны. Вычитание приведет к нулю или нет, если вы вычитаете a из b, а b и a имеют одно и то же значение, результат равен нулю. если результат равен нулю, то флаг z установлен, иначе флаг z не установлен. Таким образом, если сравнение привело к тому, что вещи равны, что совпадает с установленным флагом z, поэтому прыжок, если равен, также известен как прыжок, если ноль, прыжок, если результат был равен нулю, что совпадает с прыжком, если установлен нулевой флаг. Jne — это переход, если не равен, или переход, если нулевой флаг не установлен (иногда вы увидите jnz в зависимости от набора инструкций и синтаксиса). В вашем случае вы вычли 1234 из себя, результат был равен нулю, флаг z установлен, jne не влияет на флаги, он говорит, что переходит, если бит z равен нулю, или продолжает идти, поэтому он продолжал идти, тогда je говорит, что скачок, если флаг z установлено, что это было, поэтому он прыгнул…
Зарегистрируйтесь или войдите в систему
Зарегистрируйтесь с помощью Google
Зарегистрироваться через Facebook
Зарегистрируйтесь, используя электронную почту и пароль
Опубликовать как гость
Электронная почта
Требуется, но никогда не отображается
Опубликовать как гость
Электронная почта
Требуется, но не отображается
8086 условное кодирование перехода
8086 условное кодирование переходаВернуться на главную
- I. Тип условных переходов
- а. Список существующих прыжков
- б. Класс эквивалентности
- II. Кодирование инструкций
- а. Пункт назначения прыжка
- б. Условный прыжок
- в. Как компоновщик выбирает длинный или короткий переход
- д. Безусловные переходы
- III. Компилятор онлайн-прыжков
- IV. Углубленное изучение машинного кода
- V. Онлайн-калькулятор прыжков
I. Тип условных переходов
а. Список существующих прыжков
Код операции | Описание | Флаги ЦП | |||
---|---|---|---|---|---|
JA | Выше | CF = 0 и ZF = 0 5 JA8 9014 0150 Выше или равно | CF = 0 | ||
JB | Сильфон | CF | |||
JBE | Сильфон или аналогичный | CF или ZF | |||
JC | Carry | 1 | 0141JE | Равенство | ZF |
JG | Большее (s) | ZF = 0 и 05 JGE = 9 11181 | Большее из равного (s) | SF = OF | |
JL | Меньше (s) | SF ≠ OF | |||
JLE | Меньше равных (2) 0 ZF или SF ≠ OF | ||||
JNA | Не выше | CF или ZF | |||
JNAE | Не выше и не равно | CF | |||
JNB | Не ниже | CF = 0 | JBE | Ни ниже, ни равно | CF = 0 и ZF = 0 |
JNC | Не несет | CF = 0 | |||
JNE | Не равно | ZF = 0 |
Не больше | JNG 0151 | ZF или SF ≠ OF | |
JNGE | Не больше и не равно | SF ≠ OF | |
JNL | Не менее | SF = OF | |
ZF = 0 и SF = OF | |||
JNO | Без переполнения | OF = 0 | |
JNP | Без четности | PF = 0 | |
СФ = 0 | |||
ДНЗ | Не ноль | ZF = 0 | |
JO | Переполнение (s) | OF | |
Четность | PF | ||
JPE | Четность | PF | |
JPO | Непаритет | PF = 0 | |
JS | Отрицательный (s) | SF | 8 10154 0150 НулевойZF |
(с) подписанный режим
Два перехода не включены в предыдущий список: переходы JCXZ и JECXZ , которые не зависят от ФЛАГА ЦП но находятся в регистре CX (16 бит) или ECX (32 бита).
Инструкция безусловного перехода JMP .
б. Класс эквивалентности
Во-первых, взглянув на массив выше, мы видим, что несколько прыжков имеют одинаковые условия флага и получат одинаковый код операции.
- JB ≡ JC ≡ JNAE
- JAE ≡ JNB ≡ JNC
- JE ≡ JZ
- JNE ≡ JNZ
- JBE ≡ ЮНА
- JA ≡ JNBE
- JP ≡ JPE
- JNP ≡ JPO
- JL ≡ JNGE
- JGE ≡ JNL
- JLE ≡ JNG
- JG ≡ JNLE
Вот почему инструкция JE эквивалентна JZ. Также есть одиночные прыжки:
- ДЖО
- JNO
- JS
- JNS
Если посчитать количество прыжков, получится 16 разных случаев. Число 16 — это 2 4 или одна шестнадцатеричная цифра или также половина байта.
Затем Intel выделила 4 бита (полубайт) в коде операции для определения типа перехода.
Это значение, определяющее тип перехода, является частью кода операции. Обратите внимание на это значение $jump_type
$jump_type | Прыжки | ||
0 | JO | ||
1 | JNO | ||
2 | JBJB48 | ||
3 | JAE JNB JNC | ||
4 | JE JZ | ||
5 | JNE JNZ | ||
6 | JBE JNA | ||
7 | 11 154 | JA JN 418 | JS |
9 | JNS | ||
A | JP JPE | ||
B | JNP JPO | ||
C | JL 5 JNGE 9014 8 1 9050 JL 5 JNGE 9014 150 D | ДЖГЭ ДЖНЛ | |
Е | ДЖЛЕ ДЖНГ | ||
Ф | ДЖГ ДЖНЛЕ |
II. Код инструкции
а. Пункт назначения прыжка
Программатор использует определенные метки (блоки инструкций, номер строки, именованную метку и т. д.), но машинный код использует адреса памяти. Задача компоновщика состоит в том, чтобы вычислить и вставить эти адреса после этапа компиляции, чтобы сделать машинный код работоспособным.
Условные переходы используют относительные адреса, переходы выполняются из текущей инструкции, а расстояния определяются в байтах. Это относительное значение адреса отмечено $bytes_count
Важное примечание: адрес вычисляется с конца инструкции.
Фактически выполненный условный переход аналогичен «добавить eip, $bytes_count + инструкция_size»
$bytes_count может быть положительным или отрицательным, процессор может переходить вперед или назад.
Значение может храниться в одном байте или в одном слове (2 или 4 байта).
Компоновщик делает этот выбор во время сборки: если $bytes_count слишком велик для хранения в одном байте, тогда компоновщик использует длинный переход.
б. Условный прыжок
Машинный код состоит из кода операции и, возможно, нескольких дополнительных байтов. Условный переход составляется так:
код операции
| $bytes_count |
- код операции — это первый байт(ы) инструкции, которые должны быть распознаны ЦП.
- $jump_type (часть кода операции) указывает тип условия (см. соответствующий массив).
- $bytes_count используется для определения места перехода.
Машинный код короткого условного перехода: 7x yy; для длинного условного перехода код операции — 0F 8x yy yy yy yy.
Давайте посмотрим пример (с использованием w32dasm):
:00401000 7410 je 00401012 […] * Ссылка на (U)условный или (C)условный переход по адресу: |:00401000(К) | :00401012 40 нажатий
Машинный код 7410:
- 7 -> первая часть кода операции (короткий переход)
$jump_type = 4 -> JE / JZ (w32dasm печатает JE) - $bytes_count = 10 -> 16 байт
Переход программы с 00401000 на 00401012:
Имеем eip = 00401000
добавляем размер инструкции (2 байта) + $bytes_count (значение 0x10): 2 + 0x10 = 0x12
После инструкции перехода мы получили: eip = 00401012
Когда это длинный переход, $bytes_count сохраняется в 2 или 4 байтах в зависимости от типа программы:
- Если это 16-битная программа, то все длинные переходы имеют $bytes_count, хранящийся в 2 байтах
- Если это 32-битная программа, то все длинные переходы имеют $bytes_count, хранящийся в 4 байтах.
В отличие от Motorola, Intel меняет порядок байтов при кодировании инструкций. Такой способ упорядочения называется прямым порядком байтов.
Давайте посмотрим на пример прыжка в длину:
:00401000 0F8500010000 jne 00401106 […] * Ссылка на (U)условный или (C)условный переход по адресу: |:00401000(К) | :00401106 40 нажатий
Машинный код 0F8500100000:
- 0F8 -> первая часть кода операции (длинный переход)
$jump_type = 5 -> JNE / JNZ - $bytes_count равен «00010000»
Чтобы получить значение $bytes_count, мы переворачиваем каждый байт (каждую пару шестнадцатеричных цифр):
00010000 равно 00 01 00 00 и становится 00 00 01 00.
$bytes_count = 0x100
Переход идет на 0x106 байт вперед в памяти ($bytes_count + размер инструкции).
с. Как компоновщик выбирает длинный или короткий переход
Чтобы узнать из скольких байт компоновщик должен использовать длинный переход (вместо короткого), мы должны знать, каков максимальный ход короткого перехода.
Размер инструкции всегда 2 байта (в 16- или 32-битной программе), а $bytes_count хранится в одном байте (8 бит).
$bytes_count — это число со знаком, затем у нас есть бит знака, а остальные 7 бит используются для значения.
2 7 = 128 , $bytes_count изменится от -128 до +127 (0 здесь положительное значение).
Если мы добавим размер инструкции, реальный диапазон будет от -126 до 129.
д. Безусловные переходы
С инструкцией JMP у нас есть гораздо больше возможностей:- относительный переход, короткие и длинные переходы, такие как условные переходы
- скачки абсолютного адреса
- переход относительно значения регистра
- переход относительно значения памяти
- …
Давайте поговорим о самых распространенных и интересных прыжках, коротком и длинном относительных прыжках:
Эти переходы работают как условные переходы, меняется только заголовок кода операции. Для коротких переходов используется заголовок EB, для длинных переходов используется код операции E9..
Пример короткого прыжка:
:00401000 EB10 jmp 00401012 […] * Ссылка на (U)условный или (C)условный переход по адресу: |:00401000(К) | :00401012 40 нажатий
Длинный переход 16-битной программы:
:00401000 E jmp 00401103 […] * Ссылка на (U)условный или (C)условный переход по адресу: |:00401000(К) | :00401103 40 нажатий
Длинный переход 32-битной программы:
:00401000 E0000 jmp 00401105 […] * Ссылка на (U)условный или (C)условный переход по адресу: |:00401000(К) | :00401105 40 нажатий
Изменить короткий условный переход на безусловный очень просто: просто замените первый байт 7x на EB
Если вы обрабатываете длинный условный переход, это немного сложнее:
- два кода операции не имеют одинакового размера
- помните: $bytes_count вычисляется до конца инструкции
В этом случае мы перезаписываем инструкцией NOP первый байт кода операции условного длинного перехода
и замените второй байт кода операции инструкции длинным кодом операции JMP.
Длинный условный переход становится двумя инструкциями: NOP и JMP.
NOP — это специальная инструкция, используемая для заполнения, она ничего не делает и занимает всего один байт в памяти и один цикл процессора. Код операции NOP равен 9.0.
Например, если я хочу заставить этот условный JNS всегда прыгать
:00401000 0F80000 jns 00401106
Предложу как самую эффективную модификацию вот эту
:00401000 90 нет :00401001 E0000 jmp 00401106
III. Компилятор онлайн-прыжков
Я сделал этот небольшой компилятор, чтобы помочь вам понять. Он поддерживает только инструкции перехода и предназначен только для 32-битных программ.
: ЭББЕ
IV. Углубленное изучение машинного кода
а. Как преобразовать машинный код
Просто посмотрите снова на предыдущую таблицу:
$jump_type | Прыжки | ||
0 | JO | ||
1 | |||
JB JC JNAE | |||
3 | JAE JNB JNC | ||
4 | JE JZ | ||
5 | JNE JNZ | ||
6 | JBE JNA1 | JA JNBE | |
8 | JS | ||
9 | JNS | ||
A | JP JPE | ||
B | JNP JPO | ||
C | 9 014 JNGE | D | JGE JNL |
E | JLE JNG | ||
F | JG JNLE |
Если вы посмотрите внимательно, инженеры Intel очень хорошо упорядочили список условных переходов:
Они приписали значение $jump_type одному условию перехода и зарезервировали следующее значение для противоположного условия перехода.
Вы можете проверить с помощью первой таблицы этого документа (используя флаги ЦП), что:
- JO (0) — прыжок, противоположный JNO (1)
- JNO (1) — прыжок, противоположный JO (0)
- […]
- JNA (6) — обратный прыжок JNA (7)
- JA (7) является обратным прыжком 7A (6)
- […]
- JLE (E) xx — прыжок, противоположный JG (F)
- JG (F) — прыжок, противоположный JLE (E)
По этому поводу не так сложно найти алгоритм обратного условного перехода:
Двоичная система с основанием 2, поэтому четность числа (которая является операцией по модулю 2) получается только из последней цифры в двоичной системе, последнего бита.
Четность | Последний бит |
---|---|
Четный | 0 |
Нечетный | 1 | 8 Алгоритм работает только последний бит: