Легенда:
новое сообщение
закрытая нитка
новое сообщение
в закрытой нитке
старое сообщение
|
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
- Новичкам также крайне полезно ознакомиться с данным документом.
| |
Да нет 10.02.04 17:11 Число просмотров: 1510
Автор: amirul <Serge> Статус: The Elderman
|
Во первых в современных компилерах int и так имеет размер 32 бита (а %d - печатает именно int). Во вторых после смещения на 32 все равно 0 везде должен остаться. В третьих даже в 16-битных компилерах в little-endian архитектурах единица вылезет в старшие разряды, которые идут в памяти после младших. То бишь скорее %ld будет не нулем, чем %d
ИМХО это именно глюк
|
<programming>
|
Вот с "багом" столкнулся. 10.02.04 14:22
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
|
Это, наверное к hardware ближе...
long l = 1;
l <<= 32;
printf( "%d\n", l );
Скомпилил Симантеком - выдала 1, скомпилил стареньким Борландом - выдала 0, то же с ключиком -3 - выдала 1.
Выводы - в библиотечке для 286 двигается 32 раза, а сам поцессор (проверял на Атлоне и P-III) реагирует только на 4 младших бита.
Интересно - что на самом деле должно быть (по стандарту)?
|
|
Оказывается, это не баг, а фича Intel. Реально инструкция SHL и SHR делает сдвиг на (N mod _разрядность сдвигаемого регистра_). 11.02.04 13:08
Автор: HandleX <Александр М.> Статус: The Elderman
|
|
| |
Дополнительные исследования показали, что… 11.02.04 13:35
Автор: HandleX <Александр М.> Статус: The Elderman Отредактировано 11.02.04 13:37 Количество правок: 1
|
А вот такое уже интересней...
MOV EAX, $FFFF
SHL AX, 16
Смотрим — EAX = 0
MOV EAX, $FFFF
SHL AX, 32
Смотрим — EAX = $FFFF !
Итак, цикличность сдвига равна 32 и не зависит от разрядности сдвигаемого регистра. Интересно, как поведёт себя это дело на IA64? Скорее всего она станет равна 64. Так что делайте выводы.
|
|
А ты попробуй printf("%ld\n", l) 10.02.04 16:15
Автор: SL Статус: Незарегистрированный пользователь
|
|
| |
Да нет 10.02.04 17:11
Автор: amirul <Serge> Статус: The Elderman
|
Во первых в современных компилерах int и так имеет размер 32 бита (а %d - печатает именно int). Во вторых после смещения на 32 все равно 0 везде должен остаться. В третьих даже в 16-битных компилерах в little-endian архитектурах единица вылезет в старшие разряды, которые идут в памяти после младших. То бишь скорее %ld будет не нулем, чем %d
ИМХО это именно глюк
|
| | |
Блин, сразу не смекнул. 11.02.04 11:56
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
|
> Во первых в современных компилерах int и так имеет размер > 32 бита (а %d - печатает именно int). Во вторых после > смещения на 32 все равно 0 везде должен остаться. В третьих > даже в 16-битных компилерах в little-endian архитектурах > единица вылезет в старшие разряды, которые идут в памяти > после младших. То бишь скорее %ld будет не нулем, чем %d > > ИМХО это именно глюк Попробовал Борландом 3.1, все равно 0.
Все-таки библиотека, скорее всего честно двигает 32 раза, ну да это не важно. Обидно, что проц не сдвинул 32 раза, а нигде это не написано.
|
| | | |
Как раз про проц-то все написано. А вот про глюк компиляторов - нет. 14.02.04 04:17
Автор: AlexD <Alexander> Статус: Member
|
|
| | |
Походу, вы тут немного человека не поняли:)) 10.02.04 22:15
Автор: AlexD <Alexander> Статус: Member
|
Имелось ввиду imho следующее: вполне логично, что сдвиг мпилятор переводит и интеловскую инструкцию shl. Так вот, её второй операнд может иметь величину от 0 до 31 включительно(кажись как раз начиная с 386-х это и изменили). Соответственно на процах выше 286 инструкция shl <lya-lya>, 32 равносильна nop - ничего не делающей операции. Поэтому мы и получаем 1. На 286 же вроде не было такого ограничения(или на 8086 :-)? ) - и там выполняется полный сдвиг на 32....т.е. получаем 0. Так что, видимо, ни от каких библиотек это не зависит... Просто писатели компиляторов не учли платформно-зависимый прикол от интела...
|
| | | |
Интересно на 386 и 486 проверить было, может там напрямую... 11.02.04 12:05
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman Отредактировано 11.02.04 12:06 Количество правок: 1
|
> включительно(кажись как раз начиная с 386-х это и
Интересно на 386 и 486 проверить было бы, может там напрямую двигали, с использованием регистра сдвига и счетчика.
> изменили). Соответственно на процах выше 286 инструкция shl > <lya-lya>, 32 равносильна nop - ничего не делающей > операции. Поэтому мы и получаем 1. На 286 же вроде не было > такого ограничения(или на 8086 :-)? ) - и там выполняется > полный сдвиг на 32....т.е. получаем 0. Так что, видимо, ни > от каких библиотек это не зависит... Просто писатели
Раз уж в 286 нет инструкции сдвига 32 битного целого, похоже компилер генерит вызов встроенной функции.
> компиляторов не учли платформно-зависимый прикол от > интела...
|
| | | | |
Мне кажется так: в 286 нет 32-битных целых, но есть сдвиг на любое число от 0 до 255 14.02.04 04:15
Автор: AlexD <Alexander> Статус: Member
|
|
|
Насколько я понимаю 10.02.04 14:47
Автор: amirul <Serge> Статус: The Elderman
|
> Интересно - что на самом деле должно быть (по стандарту)? По стандарту << - операция сдвига, а не ротации. Так что единица не должна была вернуться в нулевой разряд никаким макаром. В общем 0 должен быть
|
| |
Сдвиг (<< или shl) не циклический (rol или rcl). Скорее... 11.02.04 11:42
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
|
> По стандарту << - операция сдвига, а не ротации. Так > что единица не должна была вернуться в нулевой разряд > никаким макаром. В общем 0 должен быть Сдвиг (<< или shl) не циклический (rol или rcl). Скорее всего проц посмотрел на младшие 4 разряда (а они все нули) и ничего не сдвинул.
|
| |
Может там че-то с интерпретацией carry flag компилером? 10.02.04 15:21
Автор: whiletrue <Роман> Статус: Elderman Отредактировано 10.02.04 15:24 Количество правок: 2
|
|
| | |
Я тоже сначала так подумал 10.02.04 17:01
Автор: amirul <Serge> Статус: The Elderman
|
Но тогда он должен был вылазить постоянно и после
l = 1;
l <<= 1;
l было бы равно 3
|
| | | |
Гы-ыыы! А вы попробуйте вот что... Всё-таки цикличность явно наблюдается... (updated) 11.02.04 12:36
Автор: HandleX <Александр М.> Статус: The Elderman Отредактировано 11.02.04 12:46 Количество правок: 2
|
Извините за ассемблерный Паскаль, но мне так проще ;-)
Проверьте, что возвращает вот такая функция:
Function GetRulezz: DWORD; Register;
Asm
MOV EAX, 1
SHL EAX, 35
End; ---
В общем, возвращает она 8. А если сдвигать на 34 бита, то EAX=4. А если на 33 бита, то EAX=2. Ну и надо думать, что сдвиг на 32 бита даёт единицу.
Вообще, если в регистр занести любое значение и выполнить SHL регистр, 32, то значение регистра не изменится!
-- Begin update --
О! значение регистра не меняется, если делать его сдвиг на 32 * N, где N — целое число... Причёи направление сдвига неважно — это может быть и SHR! ;-)
-- End update --
Странно, что об этом нигде не написано...
|
| | | | |
А rol, ror, rcl, rcr никто не прбовал? 11.02.04 14:55
Автор: DPP <Dmitry P. Pimenov> Статус: The Elderman
|
|
| | | | | |
Абсолютно то же с ROL и ROR, RCR и RCL (внутри) 11.02.04 15:06
Автор: HandleX <Александр М.> Статус: The Elderman Отредактировано 11.02.04 15:41 Количество правок: 2
|
Как вы думаете, что будет в EAX после исполнения следующего:
MOV EAX, 7777
RCR EAX, 32
RCL EAX, 64
ROL EAX, 96
ROR EAX, 128
SHL EAX, 160
SHR EAX, 192
Ваши предположения правильные — в регистре будет число 7777!
Ни одна из инструкций после MOV не изменила содержимое EAX (проверял отладчиком).
Вывод — IA32 в вышеуказанных инструкциях использует только младшие 5 бит во втором операнде (на сколько двигать), всё остальное отбрасывает.
Кста, на AMD тоже самое. Я думаю, это описано в спецификациях Intel, лезть на их сайт неохота ;-)
|
| | | | | | |
А мое сообщение повыше не пробовал читать:)? Я и написал, что написано в спецификации 14.02.04 04:19
Автор: AlexD <Alexander> Статус: Member
|
|
| | | | | | |
для ROL и ROR всё првилно, а для RCR и RCL нет (внутри) 12.02.04 23:41
Автор: + <Mikhail> Статус: Elderman
|
CF 7 6 5 4 3 2 1 0
+---+ +---+---+---+---+---+---+---+---+
| <---+---- | | | | | | | |<----\ (ROL)
+---+ | +---+---+---+---+---+---+---+---+ |
| <- <- <- <- <- <- <- |
| |
\------------------------------------------/
7 6 5 4 3 2 1 0 CF
+---+---+---+---+---+---+---+---+ +---+
/----> | | | | | | | ----+---> | (ROR)
| +---+---+---+---+---+---+---+---+ | +---+
| -> -> -> -> -> -> -> |
| |
\------------------------------------------/
CF 7 6 5 4 3 2 1 0
+---+ +---+---+---+---+---+---+---+---+
/--- <---- | | | | | | | |<----\ (RCL)
| +---+ +---+---+---+---+---+---+---+---+ |
| |
\---------------------------------------------------/
7 6 5 4 3 2 1 0 CF
+---+---+---+---+---+---+---+---+ +---+
/----> | | | | | | | ----> |---\ (RCR)
| +---+---+---+---+---+---+---+---+ +---+ |
| |
\---------------------------------------------------/
---
|
| | | | | | | |
А что неправильно-то? 13.02.04 06:53
Автор: HandleX <Александр М.> Статус: The Elderman
|
|
|
|