怎样以最快的速度将字节串以十六进制显示?(100分)

  • 主题发起人 主题发起人 zw84611
  • 开始时间 开始时间
Z

zw84611

Unregistered / Unconfirmed
GUEST, unregistred user!
怎样以最快的速度将字节串以十六进制显示?
例如:
data: array[0..1023] of byte;
方法1:
procedure Convert;
var
i: integer;
s: string;
begin
s := '';
for i := 0 to 1024 do s := s + format('%x',[data])
//或用IntToHex()也是一样,它也是调用format()
ShowMessage(s);
end;

方法2:
//该函数应比format('%x/',)稍快;
function ByteToHex(b: byte): String;
const
Digits : array [0..15] of char = '0123456789ABCDEF';
begin
Result := Concat(Digits[b shr 4],Digits[b and 15]);
end;

procedure Convert;
var
i: integer;
s: string;
begin
s := '';
for i := 0 to 1024 do s := s + ByteToHex(data);
ShowMessage(s);
end;
请问有没有更快的方法,那位大虾有用汇编实现的例子?
 
要那么快干什么?
1G的CPU每秒可以处理10次,你还须要多快的代码。
 
不要使用 S:=S+... 之类的字符串相加操作,在次数很多的时候,会极大的降低效率(因为
要不停的分配新的内存)。

str:=CharMemo.Text;
n:=Length(str);
SetLength(AimStr,n*2)
//一次性分配两倍于原字符串长度的空间
pc:=@AimStr[1];
pc0:=@str[1];
for i:=1 to n do
begin
FastHexWrite(pc0^,pc)
//直接填写缓冲区
Inc(pc,2);
Inc(pc0);
end;
HexMemo.Text:=AimStr;

FastHexWrite过程:
procedure FastHexWrite(const S:Char;PDest:PChar);
var
m:Byte;
begin //将字符的Hex形式写入指定地址
m:=Byte(S) shr 4
//高4位
if m<10 then
Byte(PDest^):=m+Byte('0')
else
Byte(PDest^):=m+Byte('A')-10;
m:=Byte(S) and $0F
//低4位
if m<10 then
Byte((PDest+1)^):=m+Byte('0')
else
Byte((PDest+1)^):=m+Byte('A')-10;
end;

上面的代码显示上百K的Hex速度极快。
 
多谢creation-zy,我把你的方法稍做改进如下:
data: array[0..1023] of byte;
方法3:
procedure FastHexWrite(const b:byte;PDest:PChar);
const
Digits : array [0..15] of char = '0123456789ABCDEF';
begin
PDest[0]:=Digits[b shr 4];
PDest[1]:=Digits[b and 15];
end;

procedure Convert;
var
i: integer;
s: string;
begin
SetLength(s,sizeof(data)*2);
for i := 0 to 1024 do FastHexWrite(b,@s[i*2-1]);
ShowMessage(s);
end;

请问还有更好的方法吗?
 
我找到了:
//for D5
function StringToHex(const S: string): string
register;
asm
push ebx
push esi
push edi
mov ebx, edx
mov edi, eax
call System.@LStrLen
mov edx, eax
mov esi, eax
add edx, edx
mov eax, ebx
call System.@LStrSetLength
test esi, esi
jle @@2
mov eax, ebx
call System.UniqueString
@@1: xor edx, edx
mov dl, [edi]
mov ebx, edx
shr edx, 04h
mov dl, byte ptr[edx+@@3]
and ebx, 0Fh
mov [eax], dl
mov dl, byte ptr[ebx+@@3]
inc eax
inc edi
mov [eax], dl
inc eax
dec esi
jnz @@1
@@2: pop edi
pop esi
pop ebx
ret
@@3: db '0123456789ABCDEF'
end;

//for D6
function StringToHex(const S: string): string
register;
asm
push ebx
push esi
push edi
mov ebx, edx
mov edi, eax
call System.@LStrLen
mov edx, eax
mov esi, eax
add edx, edx
mov eax, ebx
call System.@LStrSetLength
test esi, esi
jle @@2
mov eax, ebx
call System.@UniqueStringA
@@1: xor edx, edx
mov dl, [edi]
mov ebx, edx
shr edx, 04h
mov dl, [edx+@@3]
and ebx, 0Fh
mov [eax], dl
mov dl, [ebx+@@3]
inc eax
inc edi
mov [eax], dl
inc eax
dec esi
jnz @@1
@@2: pop edi
pop esi
pop ebx
ret
@@3: db '0123456789ABCDEF'
end;

但我需要的是将字节流以十六进制显示,若字节流中有#0,则调用以上函数将不能
显示完整,只能显示#0前的数据,而若改成StringToHex(const S: array of byte): 则不
能正常工作,该怎么改?
 
一般的做法是:将字符串的长度信息送入寄存器(比如ECX),然后在循环中进行比较。

真的需要用汇编吗?速度还不够快?你完全可以将FastHexWrite函数的代码在循环体中
展开:

procedure Convert;
const
Digits:array [0..15] of char='0123456789ABCDEF';
var
i:integer;
s:string;
pc:PChar;
begin
SetLength(s,sizeof(data)*2);
pc:=@s[1];
for i:=1 to 1024 do
begin
pc^:=Digits[b shr 4];
Inc(pc);
pc^:=Digits[b and 15];
Inc(pc);
end;
ShowMessage(s);
end;
 
OK,可以了。
 
后退
顶部