?

Log in

No account? Create an account
деление (компьютерное) - По делам сюда приплыл, а не за этим [entries|archive|friends|userinfo]
Anatoly Vorobey

[ website | Website ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Links
[Links:| English-language weblog ]

деление (компьютерное) [янв. 30, 2013|01:18 am]
Anatoly Vorobey
[Tags|]

Прикольно - оказывается, инструкция idiv, деление со знаком, на x86 кидает исключение не только при делении на ноль, но и когда результат не помещается в регистр. А этого очень легко добиться, написав в C например INT_MIN / -1. Как мы помним, INT_MIN по модулю на единицу больше, чем INT_MAX; например, в 32-битных числах INT_MIN равно -2147483648, а INT_MAX равно 2147483647. Поэтому когда INT_MIN делят на -1, положительный результат не вмещается в 32 бита.

Само по себе это не катастрофа - ну кидает исключение, ну и подумаешь. Дело в том, однако, что про деление на ноль все знают и помнят, и проверяют перед попыткой делить. А против INT_MIN/-1 никто практически не защищается. Поэтому можно, например:

- крэшнуть компилятор (правда, игрушечный), PostgreSQL (не игрушечную) или антивирус;
- подвесить Windows 8;
- убить bash
СсылкаОтветить

Comments:
[User Picture]From: cema
2013-01-29 11:24 pm
А ты черт! :-)
(Ответить) (Thread)
[User Picture]From: _zlot_
2013-01-29 11:39 pm
Стоп сигнал
idiv берет два параметра когда первый параметр имеет в два раза больше битов чем второй, так что даже деление на два, при неправильных параметрах выдаст overflow

http://pdos.csail.mit.edu/6.828/2011/readings/i386/IDIV.htm
(Ответить) (Thread)
[User Picture]From: archaicos
2013-01-29 11:58 pm
Это так, но код на C(++) и не только на нём всегда фактически делит N бит на N бит (т.е. в [e|r]dx оказывается только знак делиМОГО).

Edited at 2013-01-30 03:41 (UTC)
(Ответить) (Parent) (Thread)
[User Picture]From: spamsink
2013-01-29 11:42 pm
Это они зря. Microcode patch был бы полезен.
(Ответить) (Thread)
[User Picture]From: avva
2013-01-29 11:45 pm
Такое поведение во всех процессорах семьи начиная с 8086.
(Ответить) (Parent) (Thread) (Развернуть)
[User Picture]From: ahaxopet
2013-01-29 11:55 pm
bash не падает, хотя версия вроде та же:

$ ($((-2**63/-1)))
-9223372036854775808: command not found
$ bash -version
GNU bash, version 4.2.37(1)-release (i686-pc-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


Доктор, что я делаю не так? :-)
(Ответить) (Thread)
[User Picture]From: gdt
2013-01-30 12:08 am
у вас 32 бита, почитайте последний коммент по ссылке про bash.
(Ответить) (Parent) (Thread) (Развернуть)
[User Picture]From: avva
2013-01-30 12:09 am
Запускаете на 32-битной системе (а они на 64-битной).
(Ответить) (Parent) (Thread) (Развернуть)
(Удалённый комментарий)
From: rezkiy
2013-01-30 12:16 am
у них 32 разрядная.

// Product: WinNt, suite: TerminalServer SingleUserTS
// Built by: 9200.16384.x86fre.win8_rtm.120725-1247
(Ответить) (Parent) (Thread)
[User Picture]From: janatem
2013-01-30 09:46 am
Про баш там что-то странное написано:

$ ($((-2**63/-1)))

Внешние скобки порождают дочерний баш и в нем исполняется содержимое. Это вроде логично: если команда рушит баш, то сдохнет внутренний, а внешний останется жить и нам об этом сообщит. Но дальше непонятно: двойные скобки вычисляют внутреннее выражение, а доллар исполняет результат как команду. То есть $((2+3)) — это то же самое, что исполнить команду 5, должно выдать 5: command not found. Правда, в данном примере, если баш дохнет, то до попытки запуска команды под долларом дело не доходит.

Всё же логичней запускать так:

$ ( ((-2**63/-1)) )

(Ответить) (Thread)
From: huzhepidarasa
2013-01-30 11:34 am
не совсем так. $((...)) выполняет арифметику, а двойные скобки без доллара отдельного смысла не несут.
(Ответить) (Parent) (Thread) (Развернуть)
[User Picture]From: wizzard0
2013-01-30 12:52 pm
че-то винда не падает. может это 32бит онли?

в обычном приложении, впрочем, эксепшен взлетает, факт
(Ответить) (Thread)
[User Picture]From: avva
2013-01-30 12:54 pm
Это не знаю, сам не пробовал, у меня нет Windows 8.
(Ответить) (Parent) (Thread)
[User Picture]From: brandt1
2013-01-30 07:04 pm

На C# то же самое

Проверял в Visual Studio 2012, operational system Windows 2008.
Интересно, а кому это надо было - делить INT_MIN/-1?
(Ответить) (Thread)