CnPack Forum


 
Subject: Delphi与汇编学习4(两个转16进制的函数)
不得闲
灌水科科长
Rank: 3Rank: 3



UID 40680
Digest Posts 3
Credits 118
Posts 33
点点分 118
Reading Access 10
Registered 2008-7-23
Status Offline
Post at 2008-7-23 12:57  Profile | Blog | P.M. 
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进制了.
Top
不得闲
灌水科科长
Rank: 3Rank: 3



UID 40680
Digest Posts 3
Credits 118
Posts 33
点点分 118
Reading Access 10
Registered 2008-7-23
Status Offline
Post at 2008-7-24 20:44  Profile | Blog | P.M. 
关于上面的将指针区域信息转换成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 := 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;
Top
lixupeng
普通灌水员
Rank: 2



UID 33687
Digest Posts 0
Credits 66
Posts 31
点点分 66
Reading Access 10
Registered 2007-12-11
Status Offline
Post at 2008-7-24 21:46  Profile | Blog | P.M. 
不错学习下
Top
Passion (LiuXiao)
管理员
Rank: 9Rank: 9Rank: 9


UID 359
Digest Posts 19
Credits 6776
Posts 3563
点点分 6776
Reading Access 102
Registered 2004-3-28
Status Offline
Post at 2008-7-25 09:49  Profile | Blog | P.M. 
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);比较的慢。
Top
不得闲
灌水科科长
Rank: 3Rank: 3



UID 40680
Digest Posts 3
Credits 118
Posts 33
点点分 118
Reading Access 10
Registered 2008-7-23
Status Offline
Post at 2008-7-25 10:48  Profile | Blog | P.M. 
恩,应该是Memo的问题了。
Top
skyjacker
版主
Rank: 7Rank: 7Rank: 7
茶农


UID 2239
Digest Posts 9
Credits 617
Posts 269
点点分 617
Reading Access 100
Registered 2006-6-8
Status Offline
Post at 2008-7-25 12:02  Profile | Blog | P.M.  | QQ
给串口调试工具快速发数据,也会乱码。程序处理不过来啦。
用其他控件也是一样。
应该是系统处理消息的速度赶不上数据进入的速度。如果数据量大的话,界面很容易不响应。




一壶清茶煮青春.
Top
 




All times are GMT++8, the time now is 2024-6-17 07:00

    本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.0.0  © 2001-2006 Comsenz Inc.
Processed in 0.008709 second(s), 7 queries , Gzip enabled

Clear Cookies - Contact Us - CnPack Website - Archiver - WAP