Что нового

BitShift выдает неверные результаты

Rivald

Новичок
Сообщения
61
Репутация
1
Итак, в некоторых случаях в битшифте получаю совсем не то что нужно, например:
Код:
$offset = 1
MsgBox(0, '', Hex(BitShift(1342177280, -($offset))) & @CRLF & shift(1342177280, $offset))

Func shift($arg1, $arg2)
Return BitShift($arg1, -($arg2))
EndFunc

как можно заметить, первый результат верный, но второй совсем не то, хотя моя функция точно такая же. Хотелось бы узнать почему, потому что с точно такими же значениями, я использую напрямую BitShift и получаю такое же число как и в моем примере.
Ради интереса сделал еще такую функцию:
Код:
Func shift1($arg1, $arg2, $arg3)
	AsmReset($Asm)
	If $arg3 = 0 Then
		AsmAdd($Asm, "push ebp")
		AsmAdd($Asm, "mov ebp, esp")
		AsmAdd($Asm, "mov eax, [ebp + 08]")
		AsmAdd($Asm, "shl eax, " & $arg2)
		AsmAdd($Asm, "pop ebp")
		AsmAdd($Asm, "retn 4")
		ConsoleWrite(String(AsmGetBinary($Asm)) & @CRLF)
		$Ret = MemoryFuncCall("int", AsmGetPtr($Asm), "int", $arg1)
	Else
		AsmAdd($Asm, "push ebp")
		AsmAdd($Asm, "mov ebp, esp")
		AsmAdd($Asm, "mov eax, [ebp + 08]")
		AsmAdd($Asm, "shr eax, " & $arg2)
		AsmAdd($Asm, "pop ebp")
		AsmAdd($Asm, "retn 4")
		ConsoleWrite(String(AsmGetBinary($Asm)) & @CRLF)
		$Ret = MemoryFuncCall("int", AsmGetPtr($Asm), "int", $arg1)
	EndIf
	Return $Ret[0]
EndFunc   ;==>shift1

и там точно так же. Вот собственно после этого я и начал думать, что скорее всего тут я где-то лажаю.
 

sngr

AutoIT Гуру
Сообщения
1,010
Репутация
408
Код:
MsgBox(0, '', Hex(BitShift(1342177280, -($offset))) & @CRLF & shift(1342177280, $offset))
Где вызов hex для второго случая?
 
Автор
R

Rivald

Новичок
Сообщения
61
Репутация
1
Хорошо, с примером все ясно, не очень я удачно его подобрал. Но как быть в BitShiftom-ом в целевой функцие... Там у меня:
Код:
$v = BitShift($v, -($packedOffset))

и без Hex() выдает правильные значения, до определённого момента. Я проверяю это все в отладчике, тк без него никак, довольно большое кол-во условий сбивают с толку. В будущем, когда я все доделаю, через эту функцию будут проходить большое кол-во данных, поэтому вряд ли удастся как-то организовать Hex(), в тех местах где происходит ошибка.
PS
А можете еще объяснить, как вот тут получается\должно получится 80?
Код:
BitShift(0xA0000000, 25)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Как-то странно все выглядит. Вы пишите функцию на ассемблере и в то же время не знаете основ представления чисел... Единица в высшем регистре (32-ой бит) знакового числа (тип "INT") означает знак "-", т.е. отрицательное число. Это имеет значение только в десятичном представлении. Например, 0xA0000000 интерпретируется для типа "INT" как -1610612736, а для типа "UINT" как 2684354560. Но, по сути, это одно и тоже.

Rivald сказал(а):
А можете еще объяснить, как вот тут получается\должно получится 80?
Код:
BitShift(0xA0000000, 25)

10100000000000000000000000000000 (0xA0000000)

Сдвигаем биты на 25 позиций вправо:

00000000000000000000000001010000 (0x00000050)
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Еще одна особенность что все Bit... функции выполняются для 32 битовых (4 байтных) чисел. Если бы они работали с 8 байтными, то ответ вы бы получили то что хотели 80, а не -48
BitShift(0xA0000000, 25) -> BitShift(-1610612736, 25) -> -48 (Для 4 байтных)
BitShift(0xA0000000, 25) -> BitShift(2684354560, 25) -> 80 (Для 8 байтных) - но это не в AutoIt :smile:
 
Автор
R

Rivald

Новичок
Сообщения
61
Репутация
1
Вот состряпал, вроде работает!
Код:
$qwerty = tobinary(uint(-1610612736))
MsgBox(0, '', _BinaryToDec(shift($qwerty,25)))

Func shift($arg1, $count)
	$ret = ""
	$len = StringLen($arg1)
	For $i = 1 To $count
	$ret &= 0
	Next
	$ret &= StringLeft($arg1, $len - $count)
	Return $ret
EndFunc

Func tobinary($iDec)
	Local $i, $sBinChar = ""

	If StringRegExp($iDec, '[[:digit:]]') Then
		$i = 1

		Do
			$x = 16 ^ $i
			$i += 1
		Until $iDec < $x

		For $n = 4 * ($i - 1) To 1 Step -1
			If BitAND(2 ^ ($n - 1), $iDec) Then
				$sBinChar &= "1"
			Else
				$sBinChar &= "0"
			EndIf
		Next
		Return $sBinChar
	Else
		MsgBox(0, "Error", "Wrong input, try again ...")
		Return
	EndIf
EndFunc   ;==>tobinary

Func _BinaryToDec($strBin)
Local $Return
Local $lngResult
Local $intIndex

If StringRegExp($strBin,'[0-1]') then
$lngResult = 0
For $intIndex = StringLen($strBin) to 1 step -1
$strDigit = StringMid($strBin, $intIndex, 1)
Select
case $strDigit="0"
case $strDigit="1"
$lngResult = $lngResult + (2 ^ (StringLen($strBin)-$intIndex))
case else
$lngResult = 0
$intIndex = 0
EndSelect
Next

$Return = $lngResult
    Return $Return
Else
    MsgBox(0,"Error","Wrong input, try again ...")
    Return
EndIf
EndFunc

Func uint($arg1)
$str = DllStructCreate('uint;')
DllStructSetData($str, 1, $arg1)
Return DllStructGetData($str, 1)
EndFunc
 
Верх