___udivdi3 — очень не быстрая функция которая делает div сдвиги и много чего ещё.
Почему просто не использовать div, ведь "div ecx" делит EDX:EAX (64 битное число) на 32-х битное ECX ?
M>___udivdi3 — очень не быстрая функция которая делает div сдвиги и много чего ещё. M>Почему просто не использовать div, ведь "div ecx" делит EDX:EAX (64 битное число) на 32-х битное ECX ?
Просто использовать не получится. Важное свойство этой инструкции:
Overflow is indicated with the #DE (divide error) exception
т.е как минимум нормальная работа программы при переполнении закончится и (если нет особого обработчика) будет аварийное завершение.
И это задача того, кто написал инструкцию div, следить, чтобы её аргументы не вызывали переполнения.
Вот функция ___udivdi3 этим примерно и занимается — вызывает деление безопасным образом, чтобы результат получился именно тем, что написан в С++ коде.
M>на x32 платформе компилирую через gcc v10
Вообще, при делении на константу вызывать ___udivdi3 или использовать инструкцию div — неоптимальный вариант, если оптимизируется именно скорость работы (а не размер кода, например).
Все делают умножение на обратное значение, которое для констант считается во время компиляции.
В gcc 11 поправили: https://gcc.godbolt.org/z/Ga8vcPGK4
Overflow is indicated with the #DE (divide error) exception
т.е как минимум нормальная работа программы при переполнении закончится и (если нет особого обработчика) будет аварийное завершение.
M>Это же правильно, так и должна работать программа. M>А как по вашему должен поступить с++ в этом случаи ?
Вывернуто всё наоборот. Зачем С++ должен как-то поступать?
В описании языка сказано что означает та или иная конструкция, и как считать то или иное выражение, и что является наблюдаемым поведением программы.
Задача компилятора — доступными средствами воспроизвести наблюдаемое поведение.
Если временно забыть о volatile, то поведение кода
volatile дополнительно запрещает делать предположения о содержимом памяти, но это ничего не меняет в вопросе о поведении операции деления.
И компилятор должен сделать так, чтобы результат при вычислении на железе совпал с тем, который описан в стандарте языка.
Разрешено в языке выполнять деление 81985526925837671 / 5? Разрешено! Является результат однозначным и определённым? Является. Может такая пара встретится в коде ([1]
или [2])? Может!
Вот и компилятор должен сгенерировать код, который позволит получить правильный результат.
И не важно, что на x86 инструкция div не умеет делить такую пару чисел.
Разобрался! Нужно было добавить глобальный объект "My m;". Странно что без него gcc решил, что код My можно выкинуть, хотя сслыка на него была использована.