FreeBasic
Главная
Вход
Регистрация
Понедельник, 13.04.2026, 06:31Приветствую Вас Гость | RSS
[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Замена деления на единицу
zamabuvaraeuДата: Понедельник, 06.04.2026, 15:34 | Сообщение # 1
Полковник
Группа: Друзья
Сообщений: 190
Репутация: 5
Статус: Offline
Компилятор может заменить твоё деление x \ x на единицу

Например, хотим мы эмулировать ошибку деления на ноль. Просим пользлователя ввести число и делим его само на себя:
Код
' fbc -gen gcc file.bas

Dim x As Integer
Input x
Print "Ошибка деления", x \ x

В ассемблерном коде получаем, что такой инструкции x \ x не было, компилятор сократил x \ x и заменил на 1.

Потому что математически деление числа на само себя — это единица. Кроме случая, когда число равно нулю.
Однако деление на ноль — это неопределённое поведение. По главному правилу компилятора «программист пишет код без неопределённого поведения» компилятор считает, что x не может быть нулю. Следовательно, выражение можно сократить и заменить единицей.
 
DarkDemonДата: Понедельник, 06.04.2026, 18:51 | Сообщение # 2
Генерал-майор
Группа: Друзья
Сообщений: 305
Репутация: -1
Статус: Offline
Это он без опций оптимизации так своенравничает?

Да ситуация интересная, по сути это ломает отладку математических штук. Ну ту что надо отлаживать.
Т.е. доформализованная стадия прототипов. Но вообще я стараюсь ещё на этапе закладки кода избавиться от
любого возможного деления на ноль. Другой вопрос, что не всегда удаётся таких формул избегать. Хотя лучше
всё таки максимально пытаться их избегать, особенно если твои математические навыки примерно как мои))).
 
zamabuvaraeuДата: Понедельник, 06.04.2026, 19:59 | Сообщение # 3
Полковник
Группа: Друзья
Сообщений: 190
Репутация: 5
Статус: Offline
Компилятор всё «правильно» делает без всяких O1 и выше.
Эта оптимизация называется свёртка констант и работает даже на O0.
 
DarkDemonДата: Вторник, 07.04.2026, 15:18 | Сообщение # 4
Генерал-майор
Группа: Друзья
Сообщений: 305
Репутация: -1
Статус: Offline
Да в принципе можно воткнуть деление на асме, если потребуется.


Код
DIM A AS LONGINT
DIM B AS LONGINT
DIM Res AS LONGINT
DIM Ost AS LONGINT

A = -25
B = 10

ASM
  MOV rax, A     '  Делимое  (rdx:rax) 128 бит
  MOV rbx, B     '  Делитель (rbx)     64 бит

  CQO            '  Расширяем rax в rdx:rax (подготовка к делению)

  IDIV rbx       '  Знаковое целочисл. деление

  MOV Res, rax   '  Результат 64 бит в переменную Rez, остаток в регистре rdx
  MOV Ost, rdx
END ASM

PRINT "Result: "; Res
PRINT "Modulo: "; Ost
SLEEP

Только чтобы ловить исключение придётся что-то химичить с отладочными API.


Сообщение отредактировал DarkDemon - Вторник, 07.04.2026, 15:20
 
  • Страница 1 из 1
  • 1
Поиск: