2008-7-23 12:57
不得闲
Delphi与汇编学习4(两个转16进制的函数)
Delphi与汇编学习4(两个转16进制的函数)由于在工作中需要,用汇编写了一个字符串转16进制的函数,有详细注释,应该对想学习的人有所帮助的。呵呵
{功能:字符串转16进制
作者:不得闲}
function StrToHex(Const str: string): string;
asm
push ebx
push esi
push edi
test eax,eax
jz @@Exit
mov esi,edx //保存edx值,用来产生新字符串的地址
mov edi,eax //保存原字符串
mov edx,[eax-4] //获得字符串长度
mov ecx,edx //保存长度
Push ecx
add edx,edx
mov eax,esi
call System.@LStrSetLength //设置新串长度
mov eax,esi //新字符串地址
Call UniqueString //产生一个唯一的新字符串,串位置在eax中
Pop ecx
@@SetHex:
xor edx,edx //清空edx
mov dl, [edi] //Str字符串字符
mov ebx,edx //保存当前的字符
shr edx,4 //右移4字节,得到高8位
mov dl,byte ptr[edx+@@HexChar] //转换成字符
mov [eax],dl //将字符串输入到新建串中存放
and ebx,$0F //获得低8位
mov dl,byte ptr[ebx+@@HexChar] //转换成字符
inc eax //移动一个字节,存放低位
mov [eax],dl
inc edi
inc eax
loop @@SetHex
@@Exit:
pop edi
pop esi
pop ebx
ret
@@HexChar: db '0123456789ABCDEF'
end;
在群中,有人说要指针转16进制的函数,其实字符串本身就是按照指针的形式保存的,所以稍微修改一下就是指针区信息转16进制的函数了如下:
{功能:指针区信息转16进制
参数: Ptr指定指针,Len指定取得的数据长度
作者:不得闲}
function PointToHex(Const Ptr: pointer;Const Len: integer): string;
asm
Push ebx
push esi
push edi
test eax,eax
jz @@Exit
mov edi,eax
mov esi,ecx
mov ecx,edx
push ecx
add edx,edx
mov eax,esi
call System.@LStrSetLength //设置新串长度
mov eax,esi //新字符串地址
Call UniqueString //产生一个唯一的新字符串,串位置在eax中
pop ecx
@@SetHex:
xor edx,edx //清空edx
mov dl, [edi] //Str字符串字符
mov ebx,edx //保存当前的字符
shr edx,4 //右移4字节,得到高8位
mov dl,byte ptr[edx+@@HexChar] //转换成字符
mov [eax],dl //将字符串输入到新建串中存放
and ebx,$0F //获得低8位
mov dl,byte ptr[ebx+@@HexChar] //转换成字符
inc eax //移动一个字节,存放低位
mov [eax],dl
inc edi
inc eax
loop @@SetHex
@@Exit:
pop edi
pop esi
pop ebx
ret
@@HexChar: db '0123456789ABCDEF'
end;
使用比如:
var
Stream:TMemoryStream;
s: String;
i: integer;
begin
Stream := TMemoryStream.Create;
s := '不得闲';
i := 511;
Stream.WriteBuffer(pointer(s)^,Length(s));
ShowMessage(PointToHex(Stream.Memory,Stream.size));
Stream.free;
这样就把整个Stream都转换成16进制了.
2008-7-24 20:44
不得闲
关于上面的将指针区域信息转换成16进制的函数,现在碰到一个奇怪的问题,转换是很快!
但是,为什么对转换出来的字符串进行操作则很慢呢?
procedure TForm1.Button1Click(Sender: TObject);
var
BufLen,i,dwTime: integer;
buf: array of byte;
s: string;
begin
BufLen := 16384;
SetLength(Buf, BufLen);
for i := 0 to BufLen -1 do
Buf[i] := Byte(Random(256));
dwTime := GetTickCount();
//for i := 0 to 1000 -1 do
begin
s := PointToHex(@Buf[0], BufLen);
Memo1.Lines.text := s; //这里就好象死机一样
//Break;
end;
dwTime := GetTickCount - dwTime;
//ShowMessage(Format('dwTime = %d',[dwTime]));
//Memo1.Lines.Text := s;
end;
2008-7-25 09:49
Passion
Memo1.Lines.text := s;
这个速度慢是因为memo本身对很长的字符串处理性能不行的缘故吧。
改成edit1.text := s就快了。
猜想是这儿:
procedure TMemoStrings.SetTextStr(const Value: string);
var
NewText: string;
begin
NewText := AdjustLineBreaks(Value);
if (Length(NewText) <> Memo.GetTextLen) or (NewText <> Memo.Text) then
begin
if SendMessage(Memo.Handle, WM_SETTEXT, 0, Longint(NewText)) = 0 then
raise EInvalidOperation.Create(SInvalidMemoSize);
Memo.Perform(CM_TEXTCHANGED, 0, 0);
end;
end;
估计是 AdjustLineBreaks(Value);比较的慢。
2008-7-25 12:02
skyjacker
给串口调试工具快速发数据,也会乱码。程序处理不过来啦。
用其他控件也是一样。
应该是系统处理消息的速度赶不上数据进入的速度。如果数据量大的话,界面很容易不响应。