· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.ZEN —› проверка 2^n

. 1 . 2 . >>

Посл.отвђт Сообщенiе


Дата: Сен 15, 2003 04:37:56

Сколько нужно инструкций чтобы проверить что число является степенью двух?


Дата: Сен 15, 2003 04:49:22

Должна быть только одна единица. Думаю так:

; eax = input
xor ecx,ecx
next:
test eax,eax
jz done
shr eax,1
adc ecx,0
jmp next
done: cmp ecx,1
je YES
jne NO


Дата: Сен 15, 2003 05:12:44

:)
	lea edx,[eax-1]
	test eax,edx
	je @powerof2 


Дата: Сен 15, 2003 05:22:44 · Поправил: Black_mirror

The Svin
lea edx,[eax-1]
test eax,edx

Итого 5 байт.
Но можно сделать за 4 байта при том же количестве инструкций 8)

All
А если это float?


Дата: Сен 15, 2003 05:49:40

Не испортив не сделаешь.


Дата: Сен 15, 2003 06:58:05

А если это float?
Дык это больше о матемачихе :)
Что такое формат Float?
- представление в виде мантиссы и экспоненты (двоичной)
Что такое экспонента?
- степень двойки на которую умножается мантисса.
Какое число должно быть в экспоненте чтобы при умножении
на степень двойки получилась степень двойки
- классически - 1.0 - т.е. единица.
Первая единица в формате FPU опускается.
Но float разной длины - разнятся и биты выделенные под мантису (имеется ввиду индексы) поэтому нет универсального способа выделения мантисы.
А так - если там 0 - степень двойки.


Дата: Сен 15, 2003 08:31:27

super code (lea -1, test)


Дата: Сен 15, 2003 11:36:07

тут еще зависит от того, что дальше будет. Как правило, это вычисления какие-нибудь, но можно и так:
	rcr eax, 1
	jc @@odd
	; even code here
	adc eax, eax
	
@@odd:
	adc eax, eax


Дата: Сен 15, 2003 14:55:32

The Svin

поэтому нет универсального способа выделения мантисы
.data
some_float dd 128.0
.code
fld some_float
fxtract

после этого в st(0) - мантисса
в st(1) - порядок
====================
формат чисел с плавающей точкой:
для float (4 bytes) имеем:
sign (1 bit [31]) exp (8 bits [30 - 23]) fraction (23 bits [22 - 0])
для double (8 bytes):
sign (1 bit [63]) exp (11 bits [62 - 52]) fraction (51 bits [50 - 0])
для extended (10 bytes):
sign (1 bit [79]) exp (15 bits [78 - 63]) fraction (62 bits [61 - 0])

можно конечно произвести анализ мантиссы на 0, но стоит учесть особые виды чисел [0, -0, -inf, +inf, NaNs и денормализованые числа)


Дата: Сен 16, 2003 17:58:11


lea edx,[eax-1]
test eax,edx


Отладив этот код :) у меня получилось:
;4 инструкции
mov edx,1
bsf ecx,eax ;в ecx степень двойки
shl edx,cl
cmp edx,eax

или

;3 инструкции
bsf ecx,eax
shr eax,cl
cmp eax,1

...чтобы учесть eax=0


Дата: Сен 16, 2003 20:37:03

Хм... Люди ещё могут подумать что мой код вдохновил тебя на bsf :) Чур меня чур - изыди :)))
Не получилось у тебя ни 3и ни 4е - дважды отсутсвует проверочный tttn - jcc или setcc или movcc.
Ты в курсе что если в eax 0 то ecx вообще не изменится?
И тебе нужно делать проверку на ZF после BSF?
Затем вторая опущеная проверка уже после сдвига.
Итого 5 или 6 инструкций а не 3 и 4е. При этом использование медленной bsf.
Просто добавь к моему коду если нужна проверка на 0
(хотя математики до сих пор не пришли к окончательному мнению не является ли 0 степенью n в минус бесконечности).
test eax,eax
je Zcode
Остальное оставь.
Код будет работать в 2а раза быстрее и портится будет только один регистр при этом.


Дата: Сен 16, 2003 21:20:29 · Поправил: The Svin

super code (lea -1, test)
Вообще особено хитрого в коде нет, только объяснение лежит не в поле ассемблера а свойствах позиционной системы.
Можем посмотреть и в десятичной
1000 - 1 =
0999
21000 - 1 =
20999
В своё время у меня пацан додумался самостоятельно до этого приёма, правда без lea - он её не знал.
Ему помог не ассемблер а знание позиционных систем в частности бинарные паттерны.
Я думаю через несколько секунд, все кто считал это очень хитрым увидят, что это очень просто.
Сначала пара простейших патенов:
10..(х нулей в том числе и 0 нулей).. = 10^x
если число в двоичной 2^x, в десятичной 10^x
Для двоичной
11..(x единиц).. = 2^x -1.
Т.е. если мы поставим их 2^x и 2^x - 1 друг под другом, бит под битом мы увидим что 1 оказывается под нулём.
Теперь в чём разница между числом степенью двойки и не степенью?
Число не степень двойки представляет собой в бинарном виде
сумму нескольких степеней двойки.
например 1010 = 1000 + 10
И важно обратить внимание что среди этих нескольких степеней есть наименьшая среди них.
например в 1010=1000 + 10 наименьшая 10.
Вычитание единицы изменяет наименьшуюстепень и никак не изменяет остальных.
т.е. 1010 - 1 = 1000 + (10-01)= 1000+1=1001
Согласно описанию выше рисунков эта наименьшая степень обнулиться при она and (она - 1)
т.е. в примере:
1010 and 1001=1000
Но на другие (старшие) степени (биты) это не повлияет x-1
изменила только наименьшую степень-слогаемое бинарного числа, и 1000 остался в нашем примере неизменным.
Поэтому 1010 and 1001 не дал ноль - этому не дал произойти оставшийся на месте третий бит 1010 and 1001
Но это произойдёт если у нас в слогаемых-степенях числа лишь одна степень двойки и никаких "выше" её степеней
больше нет.
Например
1000 (2^3) и 0111(2^3 -1) = 0000
Особый случай когда наименьшей степенью является нулевая
(0001) также не портит этого правила в этом случае дальше
нет бит а вычитание в 2^x -1 старший бит 2^x всегда превращается в 0.

Надеюсь сейчас всё уже кажется просто банально.

Вот.
Об всех этих фокусах с использованием свойств позиционной системы в низкоуровневом программировании пишется книжеца для детей младшего и старшего возраста.


Дата: Сен 16, 2003 22:45:51 · Поправил: Fixer



Дата: Сен 16, 2003 22:46:16

The Svin

Да я в свое время делал это примерно так
   mov eax, digit
   not eax
   inc eax
   and eax, digit
   cmp eax, digit
   je  @powerof2
   

Позаимствовал у Кнута ("Исскуство программирования").

Но твой способ лучше.


Дата: Сен 17, 2003 13:54:05

Задача была такая:
Сколько нужно инструкций чтобы проверить что число является степенью двух?

Ограничений на число тактов или регистров нет :)
		; для eax=0	; для eax!=0
bsf ecx,eax	; ecx=?		; ecx=n 
shr eax,cl	; eax=0		;
dec eax		; ZF=0		; ZF=1, если eax=2^n, иначе ZF=0
;проверка закончена
;здесь нужно использовать setcc/cmovcc/jcc



Просто добавь к моему коду
test eax,eax
je Zcode


А если мне не нужны пржки и достаточно одного cmovcc или setcc???

Еще. Регистр ecx не портится, в нем возвращается N :)

. 1 . 2 . >>


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.093