在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
技术交流,DH讲解. 最近和肥鸟交流了下关于字符串方面的知识,而这篇文章是很久以前写的,现在发出来吧. 我们写两段代码来对比下: procedure TForm1.Button1Click(Sender: TObject); var a,c:Cardinal; n:Integer; D:Double; i:Integer; b:string; begin c:=0; for n:=0 to 99 do begin a:=GetTickCount; for i:=0 to 999999 do begin b:=Copy(s,1,20); end; a:=GetTickCount-a; C:=C+A; end; D:=C/100; Label1.Caption:=FloatToStr(D); end; 第二个用MoveMemory函数: procedure TForm1.Button2Click(Sender: TObject); var a,c:Cardinal; n:Integer; d:Double; i:Integer; b:string; begin c:=0; for n:=0 to 99 do begin a:=GetTickCount; for i:=0 to 999999 do begin SetLength(b,20); MoveMemory(@b[1],@s[1],20); end; a:=GetTickCount-a; C:=C+A; end; D:=C/100; Label2.Caption:=FloatToStr(D); end; 其中: procedure TForm1.FormCreate(Sender: TObject); begin s:='HuangJackyJackyHuang'; end; 看下实验数据: OK,我们看见了这个结果,可是为什么会这样呢?有朋友想了解没有? Unit1.pas.46: b:=Copy(s,1,400); lea eax,[ebp-$14] push eax mov ecx,$00000190 mov edx,$00000001 mov eax,[esi+$00000308] call @LStrCopy //跟进去 -------------@LStrCopy--------- push ebx test eax,eax jz +$2d mov ebx,[eax-$04] test ebx,ebx jz +$26 dec edx jl +$1b cmp edx,ebx jnl +$1f sub ebx,edx test ecx,ecx jl +$19 cmp ecx,ebx jnle +$11 add edx,eax mov eax,[esp+$08] //这里会跳走我们继续跟踪 call @LStrFromPCharLen jmp +$11 xor edx,edx jmp -$1b mov ecx,ebx jmp -$15 mov eax,[esp+$08] call @LStrClr pop ebx ret $0004 ret ---------@LStrFromPCharLen------------ push ebx push esi push edi mov ebx,eax mov esi,edx mov edi,ecx mov eax,edi //这里还要跟 call @NewAnsiString mov ecx,edi mov edi,eax test esi,esi jz +$09 mov edx,eax mov eax,esi //这里 call Move mov eax,ebx //这里 call @LStrClr mov [ebx],edi pop edi pop esi pop ebx ret mov eax,eax push ebp mov ebp,esp push $00 push $00 push edx push eax mov eax,[ebp+$08] ------------@NewAnsiString------------ test eax,eax jle +$24 push eax add eax,$0a and eax,-$02 push eax //继续,这里分内存了,快要到尽头了 call @GetMem pop edx mov word ptr [edx+eax-$02],$0000 add eax,$08 pop edx mov [eax-$04],edx mov [eax-$08],$00000001 ret xor eax,eax ret ------------@GetMem------------ push ebx push ecx mov ebx,eax test ebx,ebx jle +$1a mov eax,ebx //这里调用SysGetMem,我们不用跟了,因为SetLength肯定也会用到这个函数,抵消,哈哈 call dword ptr [MemoryManager] mov [esp],eax cmp dword ptr [esp],$00 jnz +$0e mov al,$01 call Error jmp +$05 xor eax,eax mov [esp],eax mov eax,[esp] pop edx pop ebx ret lea eax,[eax+$00] -------------接下来是Move 但是MoveMemory也是调用这个函数,抵消,不看了---------- -----------@LStrClr这个要进去看,不看对不起观众-------------- mov edx,[eax] test edx,edx jz +$1c mov [eax],$00000000 mov ecx,[edx-$08] dec ecx jl +$10 lock dec dword ptr [edx-$08] jnz +$0a push eax lea eax,[edx-$08] //这里又FreeMem,不看了. call @FreeMem pop eax ret nop ----------------整体过程-------------- Copy -> @LStrFromPCharLen -> @NewAnsiString -> @GetMem -> Move -> @LStrClr -> @FreeMem 好了这个流程走完. 基本上是3步,分空间,复制数据,收尾 接下来看看2的情况: Unit1.pas.71: SetLength(b,400); lea eax,[ebp-$14] mov edx,$00000190 //这个看一下 call @LStrSetLength Unit1.pas.72: MoveMemory(@b[1],@s[1],400); lea eax,[esi+$00000308] //这个干什么的 call @UniqueStringA push eax lea eax,[ebp-$14] call @UniqueStringA mov ecx,$00000190 pop edx //这里 call MoveMemory --------------@@LStrSetLength---------- push ebx push esi push edi mov ebx,eax mov esi,edx xor edi,edi test edx,edx jle +$48 mov eax,[ebx] test eax,eax jz +$23 cmp dword ptr [eax-$08],$01 jnz +$1d sub eax,$08 add edx,$09 push eax mov eax,esp call @ReallocMem pop eax add eax,$08 mov [ebx],eax mov [eax-$04],esi mov byte ptr [esi+eax],$00 //这里直接跳过去,然后就到MoveMemory这句了 jmp +$28 mov eax,edx //这个是不会被执行的. call @NewAnsiString mov edi,eax mov eax,[ebx] test eax,eax jz +$10 ------------@ReallocMem------------------ mov ecx,[eax] test ecx,ecx jz +$32 test edx,edx jz +$18 push eax mov eax,ecx call dword ptr [MemoryManager + $8] pop ecx or eax,eax jz +$19 mov [ecx],eax ret --------------@UniqueStringA---------- jmp InternalUniqueString ret mov eax,eax ----------InternalUniqueString---------- mov edx,[eax] test edx,edx jz +$38 mov ecx,[edx-$08] dec ecx jz +$32 mov eax,edx ret ---------MoveMemory--------------- xchg eax,edx call Move ret -------------------------整个过程------------------ SetLength -> @LStrSetLength -> @ReallocMem MoveMemory -> 2次@UniqueStringA -> Move ------------------------------------------------------------ 对比2个过程 今天就到这里了,我是DH. |
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论