Интересно, оператор сравнения >= выполняет 2 проверки?

Разговоры на любые темы: вы можете обсудить здесь какой-либо сайт, найти единомышленников или просто пообщаться...
kibernetics
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 945
Зарегистрирован: 03.05.2006 (Ср) 13:31
Откуда: Minsk

Интересно, оператор сравнения >= выполняет 2 проверки?

Сообщение kibernetics » 22.06.2019 (Сб) 15:01

А вот интересно, есть вариант написать сравнение как больше или равно:
a >= 5
или можно написать строго:
a > 4

так вот, в первом случае, в недрах машинных кодов в первом случае будет 2 вызова: одно на больше(>), а второе на равно(=)? Или же это одна команда?

Mikle
Изобретатель велосипедов
Изобретатель велосипедов
Аватара пользователя
 
Сообщения: 4148
Зарегистрирован: 25.03.2003 (Вт) 14:02
Откуда: Туапсе

Re: Интересно, оператор сравнения >= выполняет 2 проверки?

Сообщение Mikle » 22.06.2019 (Сб) 15:30

kibernetics писал(а):в первом случае, в недрах машинных кодов в первом случае будет 2 вызова: одно на больше(>), а второе на равно(=)?

Нет, в ассемблере есть инструкции >= и <=

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Re: Интересно, оператор сравнения >= выполняет 2 проверки?

Сообщение alibek » 22.06.2019 (Сб) 16:45

И в любом случае две проверки бы не делалось.
Делалась бы проверка на "не" "меньше".
Lasciate ogni speranza, voi ch'entrate.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Интересно, оператор сравнения >= выполняет 2 проверки?

Сообщение Хакер » 22.06.2019 (Сб) 16:56

kibernetics писал(а):в недрах машинных кодов в первом случае будет 2 вызова

В недрах машинных кодов будет одна инструкция CMP, которая выставляет флаги в регистре EFLAGS. Выставляет флаги — значит меняет значение некоторых битов на определённые (1 или 0).

В целях «экономии транзисторов» отдельная схема сравнения чисел никогда не делалась — инструкция CMP делает то же самое, что и вычитающая инструкция SUB, за исключением того, что результат вычитания одного числа из другого просто вычисляется, но никуда не сохраняется.

Поэтому, чем говорить отдельно о сравнивающей инструкции CMP, правильнее говорить о вычитающей инструкции SUB.

Если в результате вычитания получился ноль, в регистре EFLAGS устанавливается Z-флаг (Zero-flag).
Если в результате вычитания получилось число, у которого самый старший бит (который у знаковых чисел отвечает за представление отрицательных чисел) равен единицы, в регистре EFLAGS устанавливается S-флаг (Signed-flag).
Есть ряд других флаговых битов (OF, CF), которые устанавливаются в зависимости от того, были ли соблюдены во время операции вычитания определённые условия.

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

Например, инструкция JZ (Jump if zero) делает джамп, если Z-флаг (ZF) установлен, то есть если последняя арифметическая операция дала в результате ноль.
Инструкция JNZ делает (Jump if not zero) делает джамп, если Z-флаг сброшен (равен 0).

JE (jump if equal) и JNE (jump if not equal) — делают джамп, если в результате сравнения (CMP) числа были равны ли не равны. Но это не отдельные инструкции, а всего лишь альтерантивные имена для JZ и JNZ, потому что сравнение (CMP) делает под капотом то же, что вычитание (SUB), просто не сохраняет результат. И если числа были равны, то Z-флаг окажется установленным (потому что разность окажется нулевой), и тогда JE сделает джамп, а JNE не сделает, и наоборот.

Инструкции JG и JL делают джамп, исходя из того, было ли первое число больше второго при сравнении, при условии интерпретации этих чисел как знаковых. А на деле они совершает или не совершают флаг исходя их состояния S-флага.

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

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

Так что, к примеру, если в языках высокого уровня чтобы разграничить три сценария:
  • A < B
  • A = B
  • A > B
нам придётся дважды сравнивать пару чисел A и B:
If A < B Then Scenario1 ElseIf A > B Then Scenario3 Else Scenario2

То на уровне инструкций процессора достаточно один раз произвести сравнения (все необходимые для дальнейших условных переходов флаги будут установлены сразу), а потом с помощью инструкций условного перехода перейти к обработке нужного сценария:
Код: Выделить всё
CMP EAX, EBX
JG Scenario1
JL Scenario2
Scenario3 тут


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

Всё это относится к целым числам и 32-битной архитектуре x86. Для x86-64 ситуция аналогичная за исключением того, что регистры называются чуть иначе. Для чисел с плавающей точкой есть свои особенности (сравнение делается другой инструкцией, результат сравнения заносится не в EFLAGS, в флаговый регистр FPU). Для других архитектур всё может быть совсем по другому — их много, и нужно о каждой говорить отдельно.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Интересно, оператор сравнения >= выполняет 2 проверки?

Сообщение ger_kar » 22.06.2019 (Сб) 19:37

Хакер писал(а):Для других архитектур всё может быть совсем по другому — их много, и нужно о каждой говорить отдельно.
Самый первый язык программирования, который я начал изучать и на котором программировал - был ассемблер для процессора 8080 (советский аналог КР580ВМ80А). Причем по началу это был даже не ассемблер как таковой, а непосредственно сами машинные коды, которые в процессе программирования я выучил наизусть. Сейчас попытался вспомнить, как сравнение было организовано там и понял, что я напрочь все позабывал. Нет я конечно помню, что была некая операция влияющая на регистр флагов и далее команда перехода, но вот мнемоник команд (или кодов процессора) в упор не помню. Ну и всех нюансов естественно тоже. Да... Подводит память.
Бороться и искать, найти и перепрятать


Вернуться в Народный треп

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 23

    TopList  
cron