您的位置:首页 > 其它

HexToInt的几个函数速度比较

2005-04-21 09:51 381 查看
unit unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

const
  HexStr: String = 'ABCD1234';
  CalcTimes: Integer = 1000000;

type
  THexToIntFunc = function(const S: String): DWORD;

function HexToInt_tseug0(const S: String): DWORD;
asm
  PUSH EBX
  PUSH ESI

  MOV ESI, EAX //字符串地址
  MOV EDX, [EAX-4] //读取字符串长度

  XOR EAX, EAX //初始化返回值
  XOR ECX, ECX //临时变量

  TEST ESI, ESI //判断是否为空指针
  JZ @@2
  TEST EDX, EDX //判断字符串是否为空
  JLE @@2
  MOV BL, $20
@@0:
  MOV CL, [ESI]
  INC ESI

  OR CL, BL //如果有字母则被转换为小写字母
  sub CL, '0'
  JB @@2 // < '0' 的字符
  CMP CL, $09
  JBE @@1 // '0'..'9' 的字符
  sub CL, 'a'-'0'-10
  CMP CL, $0A
  JB @@2 // < 'a' 的字符
  CMP CL, $0F
  JA @@2 // > 'f' 的字符
@@1: // '0'..'9', 'A'..'F', 'a'..'f'
  SHL EAX, 4
  OR EAX, ECX
  DEC EDX
  JNZ @@0
  JMP @@3
@@2:
  XOR EAX, EAX // 非法16进制字符串
@@3:
  POP ESI
  POP EBX
  RET
end;

function HexToInt_tseug1(const S: String): DWORD;
var
  I : Integer;
begin
  Result := 0;
  for I := 1 to Length(s) do
    begin
    case s[I] of
      '0'..'9': Result := Result * 16 + Ord(S[I]) - Ord('0');
      'A'..'F': Result := Result * 16 + Ord(S[I]) - Ord('A') + 10;
      'a'..'f': Result := Result * 16 + Ord(S[I]) - Ord('a') + 10;
    else
      Result := 0;
      Exit;
      end;
    end
end;

function HexToInt_DoubleWood(const S: string): DWORD;
const
  Convert: array[0..255] of Integer =
    (
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
      0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
     -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
     -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
     );
var
  I: Integer;
  v: Integer;
begin
  Result := 0;
  if Pointer(s) = nil then exit;
  for I := 1 to PInteger(Integer(s) - 4)^ do
  begin
    begin
      V := Convert[ord(s[i])];
      if V<0 then
      begin
        Result := 0;
        Exit;
      end;
      result := (result * 16) or V;
    end;
  end;
end;

function HexToInt_beta1(const S: string): DWORD;
const
  ValidateTbl: array [0..255] of Byte = (
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 16, 16, 16, 16, 16, 16,
    16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16);
asm
  push ebx
  push ecx
  push edx
  push esi
  push edi

  mov esi, eax //字符串地址
  mov ecx, [eax-4] //读取字符串长度
  test esi, esi //判断是否为空指针
  jz @Err
  test ecx, ecx //判断字符串是否为空
  jle @Err

  xor eax, eax
  lea edi, ValidateTbl
  mov edx, ecx
  xor ebx, ebx
  @LoopValidate:
  mov bl, [esi]
  mov bl, [edi][ebx]
  test ebx, 16
  jnz @Err

  shl eax, 4
  or eax, ebx

  inc esi
  dec edx
  jnz @LoopValidate

  jmp @Ext
  @Err:
  xor eax, eax // 非法16进制字符串
  @Ext:

  pop edi
  pop esi
  pop edx
  pop ecx
  pop ebx
end;

function HexToInt_beta2(const S: string): DWORD;
const
  ValidateTbl: array [0..255] of Byte = (
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 16, 16, 16, 16, 16, 16,
    16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16);
asm
  push ebx
  push ecx
  push edx
  push esi
  push edi

  mov edi, esp
  push 0

  mov esi, eax //字符串地址
  mov ecx, [eax - 4] //读取字符串长度
  test esi, esi //判断是否为空指针
  jz @Err
  test ecx, ecx //判断字符串是否为空
  jle @Err

  lea eax, ValidateTbl
  xor edx, edx
  xor ebx, ebx

  test ecx, 1
  jz @LeftBytes

  //FirstByte:
  mov bl, [esi]
  mov bl, [eax][ebx]
  test ebx, 16
  jnz @Err
  shl bl, 4
  dec edi
  mov [edi], bl

  dec ecx
  jz @Ext

  @LeftBytes:
  mov bl, [esi]
  mov bl, [eax][ebx]
  test ebx, 16
  jnz @Err
  mov dl, bl
  shl dl, 4
  inc esi

  mov bl, [esi]
  mov bl, [eax][ebx]
  test ebx, 16
  jnz @Err
  or bl, dl
  dec edi
  mov [edi], bl
  inc esi

  dec ecx
  dec ecx
  jnz @LeftBytes

  jmp @Ext
  @Err:
  mov [esp], 0
  @Ext:
  pop eax

  pop edi
  pop esi
  pop edx
  pop ecx
  pop ebx
end;

// 测试函数,让制定的计算方法多执行几次,以拉开时间差距
function TestHexToInt(HexToIntFunc: THexToIntFunc; var Value: DWORD): DWord;
var
  I: Integer;
begin
  Result := GetTickCount;

  for I := 1 to CalcTimes do
    Value := HexToIntFunc(HexStr);

  Result := GetTickCount - Result;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Value: DWORD;
begin
  Memo1.Lines.Add(Format('HexToInt_tseug0 (%dms).', [TestHexToInt(HexToInt_tseug0, Value)]));
  Memo1.Lines.Add(Format('HexToInt_tseug1 (%dms).', [TestHexToInt(HexToInt_tseug1, Value)]));
  Memo1.Lines.Add(Format('HexToInt_DoubleWood (%dms).', [TestHexToInt(HexToInt_DoubleWood, Value)]));
  Memo1.Lines.Add(Format('HexToInt_beta1 (%dms).', [TestHexToInt(HexToInt_beta1, Value)]));
  Memo1.Lines.Add(Format('HexToInt_beta2 (%dms).', [TestHexToInt(HexToInt_beta2, Value)]));
  Memo1.Lines.Add('1234');
end;

end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息