From: Will DeWitt Jr. Subject: Fast strlen routine? NewsGroup: borland.public.delphi.language.basm Date Posted: 28-May-2003 at 13:50:4 PST Download from Google I've been tinkering with re-writing some of the standard C run-time library routines and haven't really played much with MMX instructions, or SSE for that matter. But I thought what I came up with was interesting and maybe worth sharing-- function strlenmmx(s: PAnsiChar): longword; register; asm TEST EAX, EAX JZ @@Error PXOR MM1, MM1 MOV ECX, EAX // save original pointer @@1: MOVQ MM0, [EAX] // grab 8 chars PCMPEQB MM0, MM1 // check all 8 for null/0 (00 = null, FF = not null - for each char in MM0) PMOVMSKB EDX, MM0 // move 1-bit mask of each char to DL ADD EAX, 8 // move pointer forward 8 chars TEST EDX, EDX // check for any null/0 chars JNZ @@2 MOVQ MM0, [EAX] // unroll twice (#1) PCMPEQB MM0, MM1 PMOVMSKB EDX, MM0 ADD EAX, 8 TEST EDX, EDX JNZ @@2 MOVQ MM0, [EAX] // (#2) PCMPEQB MM0, MM1 PMOVMSKB EDX, MM0 ADD EAX, 8 TEST EDX, EDX JZ @@1 @@2: EMMS BSF EDX, EDX SUB EAX, DWORD PTR [@@SubTable+EDX*4] SUB EAX, ECX RET @@SubTable: DD 8 DD 7 DD 6 DD 5 DD 4 DD 3 DD 2 DD 1 DD 0 @@Error: end;
function _PCharLen(P: _PAnsiChr): Longint; {$IFNDEF LEGACY_PCHARLEN} begin Result := 0; if P <> nil then while P[Result] <> #0 do Inc(Result); end; {$ELSE !LEGACY_PCHARLEN} {$IFDEF CPUX86} asm TEST EAX,EAX JE @@5 PUSH EAX XOR ECX,ECX @@0: CMP CL,[EAX+0] JE @@4 CMP CL,[EAX+1] JE @@3 CMP CL,[EAX+2] JE @@2 CMP CL,[EAX+3] JE @@1 ADD EAX,4 JMP @@0 @@1: INC EAX @@2: INC EAX @@3: INC EAX @@4: POP ECX SUB EAX,ECX @@5: end; {$ENDIF CPUX86} {$ENDIF !LEGACY_PCHARLEN}
http://www.verydemo.com/demo_c230_i66795.html
/* 下面是库函数中strlen的实现,比想像的要复杂 */ size_t strlen (str) const char *str; { const char *char_ptr; const unsigned long int *longword_ptr; unsigned long int longword, himagic, lomagic; for (char_ptr = str; ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0; ++char_ptr) if (*char_ptr == '