УСЛОВНЫЕ КОМАНДЫ
Условная команда — это такая команда, выполнение которой зависит от каких-либо условий. Например, требуется определенная установка флажков или необходимо наличие нуля в некотором регистре. Самыми употребительными из всех условных команд являются команды условной передачи управления.
Команды JE, JNE, JA, JB, . (и т.д.) — условная передача управления (переход, если условие удовлетворяется).
Команды SETE, SETNE, SETA, SETB, . (и т.д.) — установка байта по условию.
Команды LOOP, LOOPE/LOOPZ, LOOPNE/LOOPNZ — переход для повторения цикла.
Команды JCXZ, JECXZ — переход, если значение счетчика равно нулю.
Команды условной передачи управления
Если условие истинно (TRUE), то происходит переход по указанному адресу, иначе (FALSE) переход не происходит и выполняется следующая по порядку команда.
Для перехода задается относительный адрес, то есть, смещение относительно адреса команды, следующей после данной команды. Задаваемый на ассемблере адрес может иметь тип SHORT или тип NEAR. Адрес типа SHORT кодируется в команде всего одним байтом. Поэтому для адреса типа SHORT переход может быть только в пределах . Адрес типа NEAR кодируется двумя байтами в режиме 16 бит и четырьмя байтами в режиме 32 бита.
Всего есть 16 разных условий, им соответствует 16 разных кодов команд на уровне процессора. Но на уровне языка ассемблера эти условия превращаются в 30 разных команд. Таким образом, одна и та же команда процессора может иметь разные имена (синонимы) на языке ассемблера.
Кодирование
| Команда (asm) | Тип адреса | Код | Формат |
| J(cond) | SHORT | 70 +cond | —-cond addr(1) |
| J(cond) | NEAR | 0F 80 +cond | —-cond addr(2/4) |
Примечание. Код условия (cond) может иметь значение от 0 до F (hex).
Условия при сравнении чисел без знака
| Код (cond) | Команда (asm) | Флажки | Условие (eng) | Условие (рус) |
| 0100 | JE | ZF=1 | if equal | если равно |
| 0101 | JNE | ZF=0 | if not equal | если не равно |
| 0010 | JB /JNAE | CF=1 | if below /not above or equal | если меньше /не больше или равно |
| 0011 | JAE /JNB | CF=0 | if above or equal /not below | если больше или равно /не меньше |
| 0110 | JBE /JNA | CF=1 or ZF=1 | if below or equal /not above | если меньше или равно /не больше |
| 0111 | JA /JNBE | CF=0 and ZF=0 | if above /not below or equal | если больше /не меньше или равно |
Условия при сравнении чисел со знаком
| Код (cond) | Команда (asm) | Флажки | Условие (eng) | Условие (рус) |
| 0100 | JE | ZF=1 | if equal | если равно |
| 0101 | JNE | ZF=0 | if not equal | если не равно |
| 1100 | JL /JNGE | SF!=OF | if less /not greater or equal | если меньше /не больше или равно |
| 1101 | JGE /JNL | SF=OF | if greater or equal /not less | если больше или равно /не меньше |
| 1110 | JLE /JNG | ZF=1 or SF!=OF | if less or equal /not greater | если меньше или равно /не больше |
| 1111 | JG /JNLE | ZF=0 or SF=OF | if greater /not less or equal | если больше /не меньше или равно |
Условия по отдельным флажкам
| Код (cond) | Команда (asm) | Флажки | Условие (eng) | Условие (рус) |
| 0100 | JZ | ZF=1 | if zero | если есть флаг нуля |
| 0101 | JNZ | ZF=0 | if not zero | если нет флага нуля |
| 1000 | JS | SF=1 | if sign | если есть флаг знака |
| 1001 | JNS | SF=0 | if not sign | если нет флага знака |
| 0010 | JC | CF=1 | if carry | если есть флаг переноса |
| 0011 | JNC | CF=0 | if not carry | если нет флага переноса |
| 0000 | JO | OF=1 | if overflow | если есть флаг переполнения |
| 0001 | JNO | OF=0 | if not overflow | если нет флага переполнения |
| 1010 | JP /JPE | PF=1 | if parity /parity even | если есть флаг четности /четный |
| 1011 | JNP /JPO | PF=0 | if not parity /parity odd | если нет флага четности /нечетный |
Все условия, упорядоченные по кодам (cond)
и соответствующие коды операций
В этой таблице показаны также и соответствующие коды операций для команд с адресом типа SHORT и для команд с адресом типа NEAR.
| Код для SHORT | Код для NEAR | Код (cond) | Команда (asm) | Флажки |
| 70 | 0F 80 | 0000 | JO | OF=1 |
| 71 | 0F 81 | 0001 | JNO | OF=0 |
| 72 | 0F 82 | 0010 | JB/JNAE/JC | CF=1 |
| 73 | 0F 83 | 0011 | JAE/JNB/JNC | CF=0 |
| 74 | 0F 84 | 0100 | JE/JZ | ZF=1 |
| 75 | 0F 85 | 0101 | JNE/JNZ | ZF=0 |
| 76 | 0F 86 | 0110 | JBE/JNA | CF=1 or ZF=1 |
| 77 | 0F 87 | 0111 | JA/JNBE | CF=0 and ZF=0 |
| 78 | 0F 88 | 1000 | JS | SF=1 |
| 79 | 0F 89 | 1001 | JNS | SF=0 |
| 7A | 0F 8A | 1010 | JP/JPE | PF=1 |
| 7B | 0F 8B | 1011 | JNP/JPO | PF=0 |
| 7C | 0F 8C | 1100 | JL/JNGE | SF!=OF |
| 7D | 0F 8D | 1101 | JGE/JNL | SF=OF |
| 7E | 0F 8E | 1110 | JLE/JNG | ZF=1 or SF!=OF |
| 7F | 0F 8F | 1111 | JG/JNLE | ZF=0 or SF=OF |
Команда на языке ассемблера
| Форматы | Примеры | ||||||
| J(cond) label |
|
Команды установки байта по условию
SETE, SETNE, SETA, SETB, .
В команде установки байта SET(cond) используется тот же самый набор из 16 условий, что и в команде условной передачи управления J(cond) . И в мнемонике на языке ассемблера эти условия представляются такими же 30-ю способами.
На языке ассемблера команда имеет один операнд. Это может быть либо 8-битный регистр, либо адрес в памяти.
Команда заносит в байт, указанный в операнде, значение 1, если условие выполняется (TRUE), и значение 0 в противном случае (FALSE).
Кодирование
| Команда (asm) | Код | Формат |
| SET(cond) | 0F 90 +cond /000 | —-cond NNN |
Примечания.
1. Код условия (cond) может иметь значение от 0 до F (hex).
2. В байте (mod,reg,r/m) трехбитное поле reg должно быть равно 000.
Команда на языке ассемблера
| Форматы | Примеры | ||||||
| SET(cond) reg8 |
| ||||||
| SET(cond) mem8 |
|
Команда перехода для повторения цикла
LOOP, LOOPE/LOOPZ, LOOPNE/LOOPNZ
Эти команды используются для управления циклом со счетчиком в регистре CX (или в регистре ECX ).
При выполнении команды сначала происходит декремент (уменьшение на единицу) счетчика в регистре. (При этом никакие флажки не изменяются.) В дальнейшем, при проверке условий, действует уже измененное значение счетчика.
Если атрибут размера адреса равен 16 битам, то счетчиком служит регистр CX , если этот атрибут равен 32 битам, то регистр ECX .
Если условия (см. в таблице ниже) выполняются, то происходит переход по указанному адресу.
В условиях, кроме значения счетчика, учитывается еще и флажок нуля. Значение флажков вырабатываются командами, предшествующими команде LOOP.
Для перехода задается адрес типа SHORT, то есть, относительный адрес из одного байта. Поэтому переход может быть в пределах от (-128) до (+127) относительно адреса команды, следующей после команды LOOP.
Кодирование
См. в таблице ниже.
Команда перехода по счетчику
Переход по указанному адресу происходит в том случае, если значение счетчика равно нулю. Счетчиком служит регистр CX , если установлен режим 16 бит, или регистр ECX , если режим 32 бита.
Для перехода задается адрес типа SHORT, то есть, относительный адрес из одного байта. Поэтому переход может быть в пределах от (-128) до (+127) относительно адреса команды, следующей после команды JCXZ.
Данная команда не изменяет содержимое регистра CX (или ECX ) и не изменяет флажки.
Обычно процессор выполняет команду JCXZ дольше, чем вот такие две команды: команда сравнения содержимого регистра с нулем плюс команда условного перехода по флажку. По этой причине команда JCXZ обычно заменяется на другие команды.
What do the assembly instructions 'seta' and 'setb' do after repz cmpsb?
I’m having trouble understanding what the following lines of assembly do:
I understand after debugging, the first instruction compares the bytes in registers rsi and rdi , byte by byte.
Then it sets the lower bytes of rdx and rax according based on that instruction.
My confusion is, when I looked up this instruction online, it said seta sets the lower byte to 0x01 if its above a certain value, otherwise its 0x00. Similar for setb , which sets the byte to 0x01 if its below a certain value.
My question is what value, and how is it related to the above instruction?
Атрибуты и SET-переменные
В качестве подготовки к изучению дальнейших вопросов, связанных с условным ассемблированием, рассмотрим некоторые дополнительные возможности ассемблера.
Любые имена имеют связанные с ними атрибуты, или описательные параметры. В качестве примеров атрибутов можно рассмотреть тип имени (адрес, команда, константа), длину идентифицируемого объекта в байтах, количество символов в имени. Атрибуты могут встречаться только в выражениях, являющихся операндами команд типа SETx, или в предложениях условного ассемблирования.
Для ссылки на атрибут некоторой символической переменной мы пишем букву, соответствующую данному атрибуту, за ней апостроф и имя переменной. Например, для ссылки на тип переменной &SYM нужно написать T’&SYM.
Значением атрибута тип является символьная константа, состоящая из одной буквы. Табл. 18.1 содержит перечень наиболее часто встречающихся типов. Атрибут длины переменной &SYM записывается так L’&SYM.
Таблица 18.1 Некоторые типы переменных
А Адресная константа А-типа
В Двоичная константа
С Символьная константа
Е Константа с плавающей точкой (одинарная точность)
F Двоичное число в формате полного слова
Н Двоичное число в формате полуслова
I Машинная команда
N Самоопределенный терм (например, число или непосредственный операнд)
О Опущенный операнд
Р Упакованная десятичная константа
V Адресная константа V-типа
X Шестнадцатеричная константа
Атрибуты относятся к значению символического параметра, присвоенному с помощью данной макрокоманды. Пусть мы определили макро с именем CALC, предложение-прототип которого выглядит как
Пусть, кроме того, написана макрокоманда
COMPUTE CALC 3,LETTS,.AGAIN,NUM
где LETTS,AGAIN и NUM определены в программе как
LETTS DC CL43’ERROR NUMBER 38′
Атрибуты параметров в данном случае имеют следующие значения:
SET-переменные
Имена символических параметров задаются ассемблеру с помощью предложения-прототипа, значения параметрам присваиваются в макрокоманде. В языке ассемблера встречаются также SET-переменные, значения которым присваиваются с помощью предложений SETx (что такое х будет вскоре объяснено). С помощью предложений SETx можно выполнять арифметические, логические и символьные операции над различными переменными. Значения SET-переменных могут быть использованы для модификации машинных команд и других предложений программы. В дальнейшем мы увидим, что с помощью предложений условного ассемблирования можно производить проверки результатов подобных вычислений и в зависимости от них организовать передачи управления и циклы в процессе макрогенерации и ассемблирования.
Перед использованием любой SET-переменной ее надо определить как SET-переменную, чтобы ассемблер не считал ее с символическим параметром. Для определения SET-переменных служат предложения LCLx и GBLx. Глобальные SET-переменные (GIoBaL) сохраняют свое значение внутри всей программы, в которой они определены, причем входная информация ассемблеру должна начинаться с определений глобальных SET-переменных.

Рис. 18.6. Расположение предложений GBL и LCL в макроопределении и программе.
Локальные SET-переменные (LoCaL) сохраняют свои значения лишь внутри тех макро, в которых они были определены. Поэтому локальные переменные, пусть даже с одинаковыми именами, но определенные внутри различных макро, являются на самом деле различными. На рис. 18.6 изображена структура входных данных ассемблера, в которых определены две глобальные SET-переменные &Р и &Q, а также макро PCALC, использующее локальные переменные &R и &S. Форматы предложений GBLx и LCLx выглядят соответственно как
где «имя» — это имя символической переменной.
SET-переменные, как глобальные, так и локальные, могут быть трех типов: арифметические, булевы и символьные. Они называются соответственно SETA-, SETB- и SETC-переменными, поскольку именно такие команды применяются для присвоения им значений. Тип предложений LCLx и GBLx должен совпадать с типом переменных — LCLA или GBLA для SETA-переменных, LCLB или GBLB для SETB- переменных и т. д.
SETA-переменные используются для выполнения арифметических операций над символическими переменными. SETA-переменные всегда имеют целые значения, которые, будучи использованы в качестве операндов машинных команд, принимают вид десятичных целых. Формат SETA-предложения имеет вид
имя SETA выражение
Результатом выполнения такой команды является присвоение помеченной переменной значения, определяемого выражением, находящимся в правой части SETA. Например, если&В является SETA- переменной и имеет значение 100, то
присваивает значение 980 SETA-переменной&А (&А должно быть предварительно определено с помощью предложения LCLA или GBLA). Выражение может содержать различные символические переменные и константы,, соединенные знаками операции +, —, * и /. Выражение может также содержать атрибуты, имеющие числовые значения, например длину. Если &С— символический параметр и &CLEN — SETA-переменная, то в результате выполнения команды
переменной &CLEN присваивается значение на 10 меньшее, чем атрибут длины значения, присвоенного &С. Если затем в качестве одного из модельных предложений выступает
то полученное переменной &CLEN значение будет внесено в поле длины команды MVC.
SETB-переменные могут иметь лишь одно из двух значений: 0 или
1. Для присвоения SETB-переменным значений используются предложения, имеющие формат
имя SETB выражение
В данном случае под выражением понимается логическое выражение, которое мы рассмотрим в разд. 18.3. Если логическое выражение имеет значение «истина», то переменной, имя которой указано в поле имени SETB-предложения, присваивается значение 1, если «ложь» — то 0.
SETC-переменным значения присваиваются с помощью предложений вида
имя SETC выражение
В данном случае под выражением понимается строка символов, которая может быть образована конкатенацией нескольких строк. Каждая подстрока заключается в апострофы, за исключением случаев, когда рассматриваемое выражение, такое, как, например, атрибут типа, имеет символьную форму. Пусть, например, &CHARS представляет собой SETC-переменную. Предложение
присваивает &CHARS значение
если типом &IN являетсяТ и &GST — SETC-переменная, имеющая значение CD.
SETA-переменные, использующиеся для формирования операндов машинных команд или SETC-выражений, ведут себя как символьные представления соответствующих десятичных чисел. Может встретиться и обратная ситуация: SETC-переменные могут замещать цепочки цифр в SETA-выражении.
Как мы увидим в дальнейшем, локальные SET-переменные используются в основном внутри макро. Глобальные SET-переменные используются всякий раз при необходимости ссылаться на некоторые параметры с помощью символических имен внутри всей программы. Например, подпрограмма $$Ю составлена так, что она выполняет свои функции независимо от длины строки реально использующегося печатающего устройства. Длина строки задается при ассемблировании $$IO.
Такая задача может, например, быть решена путем введения глобальной переменной &CHRPLN, значение которой будет совпадать с количеством символов в строке. Первым предложением программы будет
Значение переменной &CHRPLN можно присвоить,например, так:
Всюду в программе, где необходимы ссылки на длину строки, можно теперь использовать SET-переменную &CHRPLN:
LINEOUT DC CL&CHRPLN.’ ‘
MVC LINEOUT + 1(&CHRPLN —1),LINEOUT
Таким образом, введенная переменная &CHRPLN встречается в программе пять или шесть раз. Для того чтобы теперь использовать 120-символьное печатающее устройство вместо 132-символьного, достаточно заменить одно предложение программы, написав
Это значительно удобнее и надежнее, чем изменение значения длины строки везде, где оно встречается в программе.