Почему IDIV с -1 вызывает исключение с плавающей запятой? - PullRequest
2 голосов
/ 25 мая 2019

Насколько я понял, idiv %ebx разделит edx:eax (объединенный в 64-битное значение в указанном порядке) с 32-битным ebx.

Однако, когда я пытаюсь разделить0x00000000:0xfffffffb (0 и -5) с 0xffffffff (-1), я получаю исключение с плавающей запятой.

Может кто-нибудь объяснить, почему?Я довольно озадачен, почему это происходит, потому что я не делю на 0 в конце концов.


Примечание , которое я знаю, мне нужно подписать расширение edx:eax, чтобы достичь того, чтоЯ хочу, чтобы рассчитать -5/-1.Однако даже без расширения знака приведенное ниже не должно вызывать FPE.

gdb screenshot

Ответы [ 2 ]

4 голосов
/ 25 мая 2019

Обратите внимание, что я знаю, что мне нужно подписать продление edx:eax ...

Если вы не подписываете расширение eax, edx:eax интерпретируется как 64-разрядное число со знаком:

В вашем случае это будет 0x00000000fffffffb, что равно 4294967291 (а не -5).

div и idiv вызовут исключение в двух случаях:

  • Вы делите на ноль
  • Результат деления не находится в диапазоне, который может быть представлен регистром eax

eax может содержать числа со знаком в диапазоне от -2147483648 до +2147483647, но -4294967291 находится вне этого диапазона. Вы получите исключение.

не должно вызывать FPE.

Действительно, div и idiv вызовут «исключение целочисленного деления», а не «исключение с плавающей запятой».

Однако во многих ОС будет отображаться сообщение «Исключение с плавающей запятой»; POSIX определяет SIGFPE как охватывающий любое арифметическое исключение.

2 голосов
/ 25 мая 2019

Когда я искал способ продлить подпись edx:eax, пока я ждал ответа на этот вопрос, я случайно нашел ответ сам.

Как указано в этом ответе , оказывается, что FPE (исключение с плавающей запятой) возникает при всех ошибках деления, в том числе при частичном переполнении деления. Связанный ответ также говорит, что обычно только -1 вызывает это частное переполнение.

Решение состоит в том, чтобы подписать расширение с помощью инструкции cdq вместо обнуления %edx.

...