Delphi按位proc转换为PHP

时间:2011-10-16 06:10:47

标签: php delphi bit-manipulation

我在Delphi中有一个相当简单的函数,它接受一个字符串并根据该字符串产生一个散列整数:

function TfrmMain.HashElf(const Buf;  BufSize : LongInt) : LongInt;
 var
 Bytes : TByteArray absolute Buf;
 I, X  : LongInt;
begin
  Result := 0;
  for I := 0 to BufSize - 1 do begin
    Result := (Result shl 4) + Bytes[I]; 
    X := Result and $F0000000;
    if (X <> 0) then  Result := Result xor (X shr 24);
    Result := Result and (not X);
  end;
end;

我正在将它转换为PHP,但结果并不相同。这就是我在PHP中所拥有的:

function HashElf($Buf, $BufSize){
  $Bytes = str_split($Buf);

  for ($i= 0; $i<$BufSize;$i++){
    $Result = ($Result << 4) + Ord($Bytes[$i]);

    $X = $Result & (0xF0000000);
    if ($X<>0){$Result = $Result ^ ($X>>24);}

    $Result = ($Result & (~ $X));
  }
  return $Result;
}

如果你将字符串teststring传递给Delphi函数,你得到195831015但PHP返回72559895.我注意到差异只在7个字符后变得明显。如果测试字符串只是测试结果是相同的。

PHP似乎在将负整数向右移动时遇到一些困难,例如下面的行:

 if ($X<>0){$Result = $Result ^ ($X>>24);}

更改为左移$ X&lt;&lt; 24为变量X生成与Delphi相同的值,但结果仍然不同。

我错过了一些非常明显的东西吗?

编辑: 这两个函数的输出是:

的Delphi

  Char: t   Result: 116        X: 0
  Char: e   Result: 1957       X: 0
  Char: s   Result: 31427      X: 0
  Char: t   Result: 502948     X: 0
  Char: s   Result: 8047283    X: 0
  Char: t   Result: 128756644  X: 0
  Char: r   Result: 181058242  X: 1879048192
  Char: i   Result: 212577321  X: -1610612736
  Char: n   Result: 180011582  X: -1073741824
  Char: g   Result: 195831015  X: -1610612736

PHP

  Char: t   $Result: 116         $X: 0
  Char: e   $Result: 1957        $X: 0
  Char: s   $Result: 31427       $X: 0
  Char: t   $Result: 502948     $X: 0
  Char: s   $Result: 8047283    $X: 0
  Char: t   $Result: 128756644  $X: 0
  Char: r   $Result: 181058242  $X: 1879048192
  Char: i   $Result: 212577417  $X: -1610612736
  Char: n   $Result: 180013310  $X: -1073741824
  Char: g   $Result: 195858503  $X: -1610612736

因此,直到字符“i”,php开始偏离计算

EDIT2:

添加了PHP函数来执行逻辑右移而不是算术移位:

function lshiftright($var,$amt)
{
  $mask = 0x40000000;
  if($var < 0)
  {
    $var &= 0x7FFFFFFF;
    $mask = $mask >> ($amt-1);
    return ($var >> $amt) | $mask;
  }else{
    return ($var >> $amt);
  }
}

这现在有效!还要感谢Ignacio的面具理念:)

2 个答案:

答案 0 :(得分:1)

掩盖你想要的位。

if ($X<>0){$Result = ($Result ^ ($X>>24)) & 0xFF;}

答案 1 :(得分:1)

你确定Delphi是对的,PHP是错的吗?

Delphi的shl和shr显然可以用签名整数表现不可预测。见:http://www.merlyn.demon.co.uk/del-bits.htm#SAR。斯托克顿博士似乎暗示有两种类型的移位操作:算术移位(保持符号)和逻辑移位。

文档(http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/devcommon/expressions_xml.html)对shl / shr对有符号整数的影响不是很清楚。然而,他们确实提到shr / shl为1仅与无符号整数的divions /乘以2相当。

我无法找到Stockton博士(来自第一个链接)调用逻辑移位操作,但似乎合乎逻辑:-)尝试更改delphi实现以使用无符号8字节类型(DWORD来到(看)有什么影响。