Loading... <p> 用这个函数进行字符串替换操作,比Delphi自带的ReplaceString要快N倍,效率一流,非常快,不愧为汇编级函数操作,哈哈.</p><p>下载函数单元文件:<a href="https://samool.com/attachments/date_200710/d6329448484dbac809be2171afb1b4e5.rar" target="_blank" >freplace.rar</a></p><div class="codeText"><div class="codeHead">delphi代码</div><ol class="dp-delphi"> <li class="alt"><span><span class="keyword">unit</span><span> FReplace; </span></span></li> <li class=""><span> </span></li> <li class="alt"><span class="keyword">interface</span><span> </span></li> <li class=""><span> </span></li> <li class="alt"><span>Type </span></li> <li class=""><span>TFastPosProc = </span><span class="keyword">function</span><span>( </span></li> <li class="alt"><span class="keyword">const</span><span> aSourceString, aFindString : String; </span></li> <li class=""><span class="keyword">const</span><span> aSourceLen, aFindLen, StartPos : </span><span class="keyword">integer</span><span> </span></li> <li class="alt"><span>) : </span><span class="keyword">integer</span><span>; </span></li> <li class=""><span> </span></li> <li class="alt"><span class="keyword">function</span><span> FastReplace( </span></li> <li class=""><span class="keyword">var</span><span> aSourceString : String; </span></li> <li class="alt"><span class="keyword">const</span><span> aFindString, aReplaceString : String; </span></li> <li class=""><span>CaseSensitive : Boolean = False) : String; </span></li> <li class="alt"><span> </span></li> <li class=""><span class="keyword">function</span><span> FastPos( </span></li> <li class="alt"><span class="keyword">const</span><span> aSourceString, aFindString : String; </span></li> <li class=""><span class="keyword">const</span><span> aSourceLen, aFindLen, StartPos : </span><span class="keyword">integer</span><span> </span></li> <li class="alt"><span>) : </span><span class="keyword">integer</span><span>; </span></li> <li class=""><span> </span></li> <li class="alt"><span class="keyword">function</span><span> FastPosNoCase( </span></li> <li class=""><span class="keyword">const</span><span> aSourceString, aFindString : String; </span></li> <li class="alt"><span class="keyword">const</span><span> aSourceLen, aFindLen, StartPos : </span><span class="keyword">integer</span><span> </span></li> <li class=""><span>) : </span><span class="keyword">integer</span><span>; </span></li> <li class="alt"><span> </span></li> <li class=""><span class="keyword">implementation</span><span> </span></li> <li class="alt"><span> </span></li> <li class=""><span class="comment">// This TYPE declaration will become apparent later. </span><span> </span></li> <li class="alt"><span class="comment">//The first thing to note here is that I’m passing the SourceLength and FindL </span><span> </span></li> <li class=""><span class="comment">//ength. As neither Source nor Find will alter at any point during FastReplace </span><span> </span></li> <li class="alt"><span class="comment">//, there’s no need to call the LENGTH subroutine each time! </span><span> </span></li> <li class=""><span class="keyword">function</span><span> FastPos( </span></li> <li class="alt"><span class="keyword">const</span><span> aSourceString, aFindString : String; </span></li> <li class=""><span class="keyword">const</span><span> aSourceLen, aFindLen, StartPos : </span><span class="keyword">integer</span><span> </span></li> <li class="alt"><span>) : </span><span class="keyword">integer</span><span>; </span></li> <li class=""><span class="keyword">var</span><span> </span></li> <li class="alt"><span>SourceLen : </span><span class="keyword">integer</span><span>; </span></li> <li class=""><span class="keyword">begin</span><span> </span></li> <li class="alt"><span> </span><span class="comment">// Next, we determine how many bytes we need to </span><span> </span></li> <li class=""><span> </span><span class="comment">// scan to find the "start" of aFindString. </span><span> </span></li> <li class="alt"><span> SourceLen := aSourceLen; </span></li> <li class=""><span> SourceLen := SourceLen - aFindLen; </span></li> <li class="alt"><span> </span><span class="keyword">if</span><span> (StartPos-</span><span class="number">1</span><span>) > SourceLen </span><span class="keyword">then</span><span> </span><span class="keyword">begin</span><span> </span></li> <li class=""><span> Result := </span><span class="number">0</span><span>; </span></li> <li class="alt"><span> Exit; </span></li> <li class=""><span> </span><span class="keyword">end</span><span>; </span></li> <li class="alt"><span> SourceLen := SourceLen - StartPos; </span></li> <li class=""><span> SourceLen := SourceLen +</span><span class="number">2</span><span>; </span></li> <li class="alt"><span> </span><span class="comment">// The ASM starts here. </span><span> </span></li> <li class=""><span> </span><span class="keyword">asm</span><span> </span></li> <li class="alt"><span> </span><span class="comment">// Delphi uses ESI, EDI, and EBX a lot, </span><span> </span></li> <li class=""><span> </span><span class="comment">// so we must preserve them. </span><span> </span></li> <li class="alt"><span> push ESI </span></li> <li class=""><span> push EDI </span></li> <li class="alt"><span> push EBX </span></li> <li class=""><span> </span><span class="comment">// Get the address of sourceString[1] </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// and Add (StartPos-1). </span><span> </span></li> <li class=""><span> </span><span class="comment">// We do this for the purpose of finding </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// the NEXT occurrence, rather than </span><span> </span></li> <li class=""><span> </span><span class="comment">// always the first! </span><span> </span></li> <li class="alt"><span> mov EDI, aSourceString </span></li> <li class=""><span> add EDI, StartPos </span></li> <li class="alt"><span> Dec EDI </span></li> <li class=""><span> </span><span class="comment">// Get the address of aFindString. </span><span> </span></li> <li class="alt"><span> mov ESI, aFindString </span></li> <li class=""><span> </span><span class="comment">// Note how many bytes we need to </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// look through in aSourceString </span><span> </span></li> <li class=""><span> </span><span class="comment">// to find aFindString. </span><span> </span></li> <li class="alt"><span> mov ECX, SourceLen </span></li> <li class=""><span> </span><span class="comment">// Get the first char of aFindString; </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// note how it is done outside of the </span><span> </span></li> <li class=""><span> </span><span class="comment">// main loop, as it never changes! </span><span> </span></li> <li class="alt"><span> Mov Al, [ESI] </span></li> <li class=""><span> </span><span class="comment">// Now the FindFirstCharacter loop! </span><span> </span></li> <li class="alt"><span> @ScaSB: </span></li> <li class=""><span> </span><span class="comment">// Get the value of the current </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// character in aSourceString. </span><span> </span></li> <li class=""><span> </span><span class="comment">// This is equal to ah := EDI^, that </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// is what the [] are around [EDI]. </span><span> </span></li> <li class=""><span> Mov Ah, [EDI] </span></li> <li class="alt"><span> </span><span class="comment">// Compare this character with aDestString[1]. </span><span> </span></li> <li class=""><span> cmp Ah,Al </span></li> <li class="alt"><span> </span><span class="comment">// If they're not equal we don't </span><span> </span></li> <li class=""><span> </span><span class="comment">// compare the strings. </span><span> </span></li> <li class="alt"><span> jne @NextChar </span></li> <li class=""><span> </span><span class="comment">// If they're equal, obviously we do! </span><span> </span></li> <li class="alt"><span> @CompareStrings: </span></li> <li class=""><span> </span><span class="comment">// Put the length of aFindLen in EBX. </span><span> </span></li> <li class="alt"><span> mov EBX, aFindLen </span></li> <li class=""><span> </span><span class="comment">// We DEC EBX to point to the end of </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// the string; that is, we don't want to </span><span> </span></li> <li class=""><span> </span><span class="comment">// add 1 if aFindString is 1 in length! </span><span> </span></li> <li class="alt"><span> dec EBX </span></li> <li class=""><span> </span></li> <li class="alt"><span> </span><span class="comment">// add by ShengQuanhu </span><span> </span></li> <li class=""><span> </span><span class="comment">// If EBX is zero, then we've successfully </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// compared each character; i.e. it's A MATCH! </span><span> </span></li> <li class=""><span> </span><span class="comment">// It will be happened when aFindLen=1 </span><span> </span></li> <li class="alt"><span> Jz @EndOfMatch </span></li> <li class=""><span> </span><span class="comment">//add end </span><span> </span></li> <li class="alt"><span> </span></li> <li class=""><span> </span><span class="comment">//Here’s another optimization tip. People at this point usually PUSH ESI and </span><span> </span></li> <li class="alt"><span class="comment">//so on and then POP ESI and so forth at the end–instead, I opted not to chan </span><span> </span></li> <li class=""><span class="comment">//ge ESI and so on at all. This saves lots of pushing and popping! </span><span> </span></li> <li class="alt"><span> @CompareNext: </span></li> <li class=""><span> </span><span class="comment">// Get aFindString character + </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// aFindStringLength (the last char). </span><span> </span></li> <li class=""><span> mov Al, [ESI+EBX] </span></li> <li class="alt"><span> </span><span class="comment">// Get aSourceString character (current </span><span> </span></li> <li class=""><span> </span><span class="comment">// position + aFindStringLength). </span><span> </span></li> <li class="alt"><span> mov Ah, [EDI+EBX] </span></li> <li class=""><span> </span><span class="comment">// Compare them. </span><span> </span></li> <li class="alt"><span> cmp Al, Ah </span></li> <li class=""><span> Jz @Matches </span></li> <li class="alt"><span> </span><span class="comment">// If they don't match, we put the first char </span><span> </span></li> <li class=""><span> </span><span class="comment">// of aFindString into Al again to continue </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// looking for the first character. </span><span> </span></li> <li class=""><span> Mov Al, [ESI] </span></li> <li class="alt"><span> Jmp @NextChar </span></li> <li class=""><span> @Matches: </span></li> <li class="alt"><span> </span><span class="comment">// If they match, we DEC EBX (point to </span><span> </span></li> <li class=""><span> </span><span class="comment">// previous character to compare). </span><span> </span></li> <li class="alt"><span> Dec EBX </span></li> <li class=""><span> </span><span class="comment">// If EBX <> 0 ("J"ump "N"ot "Z"ero), we </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// continue comparing strings. </span><span> </span></li> <li class=""><span> Jnz @CompareNext </span></li> <li class="alt"><span> </span></li> <li class=""><span> </span><span class="comment">//add by Shengquanhu </span><span> </span></li> <li class="alt"><span> @EndOfMatch: </span></li> <li class=""><span> </span><span class="comment">//add end </span><span> </span></li> <li class="alt"><span> </span></li> <li class=""><span> </span><span class="comment">// If EBX is zero, then we've successfully </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// compared each character; i.e. it's A MATCH! </span><span> </span></li> <li class=""><span> </span><span class="comment">// Move the address of the *current* </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// character in EDI. </span><span> </span></li> <li class=""><span> </span><span class="comment">// Note, we haven't altered EDI since </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// the first char was found. </span><span> </span></li> <li class=""><span> mov EAX, EDI </span></li> <li class="alt"><span> </span><span class="comment">// This is an address, so subtract the </span><span> </span></li> <li class=""><span> </span><span class="comment">// address of aSourceString[1] to get </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// an actual character position. </span><span> </span></li> <li class=""><span> sub EAX, aSourceString </span></li> <li class="alt"><span> </span><span class="comment">// Inc EAX to make it 1-based, </span><span> </span></li> <li class=""><span> </span><span class="comment">// rather than 0-based. </span><span> </span></li> <li class="alt"><span> inc EAX </span></li> <li class=""><span> </span><span class="comment">// Put it into result. </span><span> </span></li> <li class="alt"><span> mov Result, EAX </span></li> <li class=""><span> </span><span class="comment">// Finish this routine! </span><span> </span></li> <li class="alt"><span> jmp @TheEnd </span></li> <li class=""><span> @NextChar: </span></li> <li class="alt"><span> </span><span class="comment">//This is where I jump to when I want to continue searching for the first char </span><span> </span></li> <li class=""><span class="comment">//acter of aFindString in aSearchString: </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// Point EDI (aFindString[X]) to </span><span> </span></li> <li class=""><span> </span><span class="comment">// the next character. </span><span> </span></li> <li class="alt"><span> Inc EDI </span></li> <li class=""><span> </span><span class="comment">// Dec ECX tells us that we've checked </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// another character, and that we're </span><span> </span></li> <li class=""><span> </span><span class="comment">// fast running out of string to check! </span><span> </span></li> <li class="alt"><span> dec ECX </span></li> <li class=""><span> </span><span class="comment">// If EBX <> 0, then continue scanning </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// for the first character. </span><span> </span></li> <li class=""><span> </span></li> <li class="alt"><span> </span><span class="comment">//add by shengquanhu </span><span> </span></li> <li class=""><span> </span><span class="comment">//if ah is chinese char,jump again </span><span> </span></li> <li class="alt"><span> jz @Result0 </span></li> <li class=""><span> cmp ah, </span><span class="number">$80</span><span> </span></li> <li class="alt"><span> jb @ScaSB </span></li> <li class=""><span> Inc EDI </span></li> <li class="alt"><span> Dec ECX </span></li> <li class=""><span> </span><span class="comment">//add by shengquanhu end </span><span> </span></li> <li class="alt"><span> </span></li> <li class=""><span> jnz @ScaSB </span></li> <li class="alt"><span> </span></li> <li class=""><span> </span><span class="comment">//add by shengquanhu </span><span> </span></li> <li class="alt"><span> @Result0: </span></li> <li class=""><span> </span><span class="comment">//add by shengquanhu end </span><span> </span></li> <li class="alt"><span> </span></li> <li class=""><span> </span><span class="comment">// If EBX = 0, then move 0 into RESULT. </span><span> </span></li> <li class="alt"><span> mov Result,</span><span class="number">0</span><span> </span></li> <li class=""><span> </span><span class="comment">// Restore EBX, EDI, ESI for Delphi </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// to work correctly. </span><span> </span></li> <li class=""><span> </span><span class="comment">// Note that they're POPped in the </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// opposite order they were PUSHed. </span><span> </span></li> <li class=""><span> @TheEnd: </span></li> <li class="alt"><span> pop EBX </span></li> <li class=""><span> pop EDI </span></li> <li class="alt"><span> pop ESI </span></li> <li class=""><span> </span><span class="keyword">end</span><span>; </span></li> <li class="alt"><span class="keyword">end</span><span>; </span></li> <li class=""><span> </span></li> <li class="alt"><span class="comment">//This routine is an identical copy of FastPOS except where commented! The ide </span><span> </span></li> <li class=""><span class="comment">//a is that when grabbing bytes, it ANDs them with $df, effectively making the </span><span> </span></li> <li class="alt"><span class="comment">//m lowercase before comparing. Maybe this would be quicker if aFindString was </span><span> </span></li> <li class=""><span class="comment">// made lowercase in one fell swoop at the beginning of the function, saving a </span><span> </span></li> <li class="alt"><span class="comment">//n AND instruction each time. </span><span> </span></li> <li class=""><span class="keyword">function</span><span> FastPosNoCase( </span></li> <li class="alt"><span class="keyword">const</span><span> aSourceString, aFindString : String; </span></li> <li class=""><span class="keyword">const</span><span> aSourceLen, aFindLen, StartPos : </span><span class="keyword">integer</span><span> </span></li> <li class="alt"><span>) : </span><span class="keyword">integer</span><span>; </span></li> <li class=""><span class="keyword">var</span><span> </span></li> <li class="alt"><span>SourceLen : </span><span class="keyword">integer</span><span>; </span></li> <li class=""><span class="keyword">begin</span><span> </span></li> <li class="alt"><span> SourceLen := aSourceLen; </span></li> <li class=""><span> SourceLen := SourceLen - aFindLen; </span></li> <li class="alt"><span> </span><span class="keyword">if</span><span> (StartPos-</span><span class="number">1</span><span>) > SourceLen </span><span class="keyword">then</span><span> </span><span class="keyword">begin</span><span> </span></li> <li class=""><span> Result := </span><span class="number">0</span><span>; </span></li> <li class="alt"><span> Exit; </span></li> <li class=""><span> </span><span class="keyword">end</span><span>; </span></li> <li class="alt"><span> SourceLen := SourceLen - StartPos; </span></li> <li class=""><span> SourceLen := SourceLen +</span><span class="number">2</span><span>; </span></li> <li class="alt"><span> </span><span class="keyword">asm</span><span> </span></li> <li class=""><span> push ESI </span></li> <li class="alt"><span> push EDI </span></li> <li class=""><span> push EBX </span></li> <li class="alt"><span> </span></li> <li class=""><span> mov EDI, aSourceString </span></li> <li class="alt"><span> add EDI, StartPos </span></li> <li class=""><span> Dec EDI </span></li> <li class="alt"><span> mov ESI, aFindString </span></li> <li class=""><span> mov ECX, SourceLen </span></li> <li class="alt"><span> Mov Al, [ESI] </span></li> <li class=""><span> </span></li> <li class="alt"><span> </span><span class="comment">//add by shengquanhu:just modified the lowercase 'a'..'z' </span><span> </span></li> <li class=""><span> cmp Al, </span><span class="number">$7A</span><span> </span></li> <li class="alt"><span> ja @ScaSB </span></li> <li class=""><span> </span></li> <li class="alt"><span> cmp Al, </span><span class="number">$61</span><span> </span></li> <li class=""><span> jb @ScaSB </span></li> <li class="alt"><span> </span><span class="comment">//end------------------------------------------ </span><span> </span></li> <li class=""><span> </span></li> <li class="alt"><span> </span><span class="comment">// Make Al uppercase. </span><span> </span></li> <li class=""><span> </span><span class="keyword">and</span><span> Al, </span><span class="number">$df</span><span> </span></li> <li class="alt"><span> </span></li> <li class=""><span> @ScaSB: </span></li> <li class="alt"><span> Mov Ah, [EDI] </span></li> <li class=""><span> </span></li> <li class="alt"><span> </span><span class="comment">//add by shengquanhu:just modified the lowercase 'a'..'z' </span><span> </span></li> <li class=""><span> cmp Ah, </span><span class="number">$7A</span><span> </span></li> <li class="alt"><span> ja @CompareChar </span></li> <li class=""><span> </span></li> <li class="alt"><span> cmp Ah, </span><span class="number">$61</span><span> </span></li> <li class=""><span> jb @CompareChar </span></li> <li class="alt"><span> </span><span class="comment">//end------------------------------------------ </span><span> </span></li> <li class=""><span> </span></li> <li class="alt"><span> </span><span class="comment">// Make Ah uppercase. </span><span> </span></li> <li class=""><span> </span><span class="keyword">and</span><span> Ah, </span><span class="number">$df</span><span> </span></li> <li class="alt"><span> </span></li> <li class=""><span> @CompareChar: </span></li> <li class="alt"><span> cmp Ah,Al </span></li> <li class=""><span> jne @NextChar </span></li> <li class="alt"><span> @CompareStrings: </span></li> <li class=""><span> mov EBX, aFindLen </span></li> <li class="alt"><span> dec EBX </span></li> <li class=""><span> </span></li> <li class="alt"><span> </span><span class="comment">//add by ShengQuanhu </span><span> </span></li> <li class=""><span> Jz @EndOfMatch </span></li> <li class="alt"><span> </span><span class="comment">//add end </span><span> </span></li> <li class=""><span> </span></li> <li class="alt"><span> @CompareNext: </span></li> <li class=""><span> mov Al, [ESI+EBX] </span></li> <li class="alt"><span> mov Ah, [EDI+EBX] </span></li> <li class=""><span> </span></li> <li class="alt"><span> </span><span class="comment">//add by shengquanhu:just modified the lowercase 'a'..'z' </span><span> </span></li> <li class=""><span> cmp Ah, </span><span class="number">$7A</span><span> </span></li> <li class="alt"><span> ja @LowerAh </span></li> <li class=""><span> </span></li> <li class="alt"><span> cmp Al, </span><span class="number">$61</span><span> </span></li> <li class=""><span> jb @LowerAh </span></li> <li class="alt"><span> </span><span class="comment">//end------------------------------------------ </span><span> </span></li> <li class=""><span> </span></li> <li class="alt"><span> </span><span class="comment">// Make Al and Ah uppercase. </span><span> </span></li> <li class=""><span> </span><span class="keyword">and</span><span> Al, </span><span class="number">$df</span><span> </span></li> <li class="alt"><span> </span></li> <li class=""><span> </span><span class="comment">//add by shengquanhu:just modified the lowercase 'a'..'z' </span><span> </span></li> <li class="alt"><span> @LowerAh: </span></li> <li class=""><span> cmp Ah, </span><span class="number">$7A</span><span> </span></li> <li class="alt"><span> ja @CompareChar2 </span></li> <li class=""><span> </span></li> <li class="alt"><span> cmp Ah, </span><span class="number">$61</span><span> </span></li> <li class=""><span> jb @CompareChar2 </span></li> <li class="alt"><span> </span><span class="comment">//end------------------------------------------ </span><span> </span></li> <li class=""><span> </span></li> <li class="alt"><span> </span><span class="keyword">and</span><span> Ah, </span><span class="number">$df</span><span> </span></li> <li class=""><span> </span></li> <li class="alt"><span> @CompareChar2: </span></li> <li class=""><span> cmp Al, Ah </span></li> <li class="alt"><span> Jz @Matches </span></li> <li class=""><span> Mov Al, [ESI] </span></li> <li class="alt"><span> </span></li> <li class=""><span> </span><span class="comment">//add by shengquanhu:just modified the lowercase 'a'..'z' </span><span> </span></li> <li class="alt"><span> cmp Al, </span><span class="number">$7A</span><span> </span></li> <li class=""><span> ja @NextChar </span></li> <li class="alt"><span> </span></li> <li class=""><span> cmp Al, </span><span class="number">$61</span><span> </span></li> <li class="alt"><span> jb @NextChar </span></li> <li class=""><span> </span><span class="comment">//end------------------------------------------ </span><span> </span></li> <li class="alt"><span> </span></li> <li class=""><span> </span><span class="comment">// Make Al uppercase. </span><span> </span></li> <li class="alt"><span> </span><span class="keyword">and</span><span> Al, </span><span class="number">$df</span><span> </span></li> <li class=""><span> Jmp @NextChar </span></li> <li class="alt"><span> @Matches: </span></li> <li class=""><span> Dec EBX </span></li> <li class="alt"><span> Jnz @CompareNext </span></li> <li class=""><span> </span></li> <li class="alt"><span> </span><span class="comment">//add by Shengquanhu </span><span> </span></li> <li class=""><span> @EndOfMatch: </span></li> <li class="alt"><span> </span><span class="comment">//add end </span><span> </span></li> <li class=""><span> </span></li> <li class="alt"><span> mov EAX, EDI </span></li> <li class=""><span> sub EAX, aSourceString </span></li> <li class="alt"><span> inc EAX </span></li> <li class=""><span> mov Result, EAX </span></li> <li class="alt"><span> jmp @TheEnd </span></li> <li class=""><span> @NextChar: </span></li> <li class="alt"><span> Inc EDI </span></li> <li class=""><span> dec ECX </span></li> <li class="alt"><span> </span><span class="comment">//add by shengquanhu </span><span> </span></li> <li class=""><span> </span><span class="comment">//if ah is chinese char,jump again </span><span> </span></li> <li class="alt"><span> jz @Result0 </span></li> <li class=""><span> cmp ah, </span><span class="number">$80</span><span> </span></li> <li class="alt"><span> jb @ScaSB </span></li> <li class=""><span> Inc EDI </span></li> <li class="alt"><span> Dec ECX </span></li> <li class=""><span> </span><span class="comment">//add by shengquanhu end </span><span> </span></li> <li class="alt"><span> jnz @ScaSB </span></li> <li class=""><span> @Result0: </span></li> <li class="alt"><span> mov Result,</span><span class="number">0</span><span> </span></li> <li class=""><span> @TheEnd: </span></li> <li class="alt"><span> pop EBX </span></li> <li class=""><span> pop EDI </span></li> <li class="alt"><span> pop ESI </span></li> <li class=""><span> </span><span class="keyword">end</span><span>; </span></li> <li class="alt"><span class="keyword">end</span><span>; </span></li> <li class=""><span> </span></li> <li class="alt"><span class="comment">//My move isn’t as fast as MOVE when source and destination are both DWord al </span><span> </span></li> <li class=""><span class="comment">//igned, but it’s certainly faster when they’re not. As we’re moving charac </span><span> </span></li> <li class="alt"><span class="comment">//ters in a string, it isn’t very likely at all that both source and destinat </span><span> </span></li> <li class=""><span class="comment">//ion are DWord aligned, so moving bytes avoids the cycle penalty of reading/w </span><span> </span></li> <li class="alt"><span class="comment">//riting DWords across physical boundaries. </span><span> </span></li> <li class=""><span class="keyword">procedure</span><span> MyMove( </span></li> <li class="alt"><span class="keyword">const</span><span> Source; </span><span class="keyword">var</span><span> Dest; Count : Integer); </span></li> <li class=""><span class="keyword">asm</span><span> </span></li> <li class="alt"><span> </span><span class="comment">// Note: When this function is called, </span><span> </span></li> <li class=""><span class="comment">// Delphi passes the parameters as follows: </span><span> </span></li> <li class="alt"><span class="comment">// ECX = Count </span><span> </span></li> <li class=""><span class="comment">// EAX = Const Source </span><span> </span></li> <li class="alt"><span class="comment">// EDX = Var Dest </span><span> </span></li> <li class=""><span> </span><span class="comment">// If there are no bytes to copy, just quit </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// altogether; there's no point pushing registers. </span><span> </span></li> <li class=""><span> cmp ECX,</span><span class="number">0</span><span> </span></li> <li class="alt"><span> Je @JustQuit </span></li> <li class=""><span> </span><span class="comment">// Preserve the critical Delphi registers. </span><span> </span></li> <li class="alt"><span> push ESI </span></li> <li class=""><span> push EDI </span></li> <li class="alt"><span> </span><span class="comment">// Move Source into ESI (generally the </span><span> </span></li> <li class=""><span> </span><span class="comment">// SOURCE register). </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// Move Dest into EDI (generally the DEST </span><span> </span></li> <li class=""><span> </span><span class="comment">// register for string commands). </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// This might not actually be necessary, </span><span> </span></li> <li class=""><span> </span><span class="comment">// as I'm not using MOVsb etc. </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// I might be able to just use EAX and EDX; </span><span> </span></li> <li class=""><span> </span><span class="comment">// there could be a penalty for not using </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// ESI, EDI, but I doubt it. </span><span> </span></li> <li class=""><span> </span><span class="comment">// This is another thing worth trying! </span><span> </span></li> <li class="alt"><span> mov ESI, EAX </span></li> <li class=""><span> mov EDI, EDX </span></li> <li class="alt"><span> </span><span class="comment">// The following loop is the same as repNZ </span><span> </span></li> <li class=""><span> </span><span class="comment">// MovSB, but oddly quicker! </span><span> </span></li> <li class="alt"><span> @Loop: </span></li> <li class=""><span> </span><span class="comment">// Get the source byte. </span><span> </span></li> <li class="alt"><span> Mov AL, [ESI] </span></li> <li class=""><span> </span><span class="comment">// Point to next byte. </span><span> </span></li> <li class="alt"><span> Inc ESI </span></li> <li class=""><span> </span><span class="comment">// Put it into the Dest. </span><span> </span></li> <li class="alt"><span> mov [EDI], AL </span></li> <li class=""><span> </span><span class="comment">// Point dest to next position. </span><span> </span></li> <li class="alt"><span> Inc EDI </span></li> <li class=""><span> </span><span class="comment">// Dec ECX to note how many we have left to copy. </span><span> </span></li> <li class="alt"><span> Dec ECX </span></li> <li class=""><span> </span><span class="comment">// If ECX <> 0, then loop. </span><span> </span></li> <li class="alt"><span> Jnz @Loop </span></li> <li class=""><span> </span><span class="comment">// Another optimization note. </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// Many people like to do this. </span><span> </span></li> <li class=""><span> </span><span class="comment">// Mov AL, [ESI] </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// Mov [EDI], Al </span><span> </span></li> <li class=""><span> </span><span class="comment">// Inc ESI </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// Inc ESI </span><span> </span></li> <li class=""><span class="comment">//There’s a hidden problem here. I won’t go into too much detail, but the Pe </span><span> </span></li> <li class="alt"><span class="comment">//ntium can continue processing instructions while it’s still working out the </span><span> </span></li> <li class=""><span class="comment">// result of INC ESI or INC EDI. If, however, you use them while they’re stil </span><span> </span></li> <li class="alt"><span class="comment">//l being calculated, the processor will stop until they’re calculated (a pen </span><span> </span></li> <li class=""><span class="comment">//alty). Therefore, I alter ESI and EDI as far in advance as possible of using </span><span> </span></li> <li class="alt"><span class="comment">// them. </span><span> </span></li> <li class=""><span> </span><span class="comment">// Pop the critical Delphi registers </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// that we've altered. </span><span> </span></li> <li class=""><span> pop EDI </span></li> <li class="alt"><span> pop ESI </span></li> <li class=""><span> @JustQuit: </span></li> <li class="alt"><span class="keyword">end</span><span>; </span></li> <li class=""><span> </span></li> <li class="alt"><span class="comment">//Point 1: I pass VAR aSourceString rather than just aSourceString. This is be </span><span> </span></li> <li class=""><span class="comment">//cause I’ll just be passed a pointer to the data rather than a 10M copy of t </span><span> </span></li> <li class="alt"><span class="comment">//he data itself, which is much quicker! </span><span> </span></li> <li class=""><span class="keyword">function</span><span> FastReplace( </span></li> <li class="alt"><span class="keyword">var</span><span> aSourceString : String; </span></li> <li class=""><span class="keyword">const</span><span> aFindString, aReplaceString : String; </span></li> <li class="alt"><span>CaseSensitive : Boolean = False) : String; </span></li> <li class=""><span class="keyword">var</span><span> </span></li> <li class="alt"><span class="comment">// Size already passed to SetLength, </span><span> </span></li> <li class=""><span> </span><span class="comment">// the REAL size of RESULT. </span><span> </span></li> <li class="alt"><span> ActualResultLen, </span></li> <li class=""><span class="comment">// Position of aFindString is aSourceString. </span><span> </span></li> <li class="alt"><span> CurrentPos, </span></li> <li class=""><span class="comment">// Last position the aFindString was found at. </span><span> </span></li> <li class="alt"><span> LastPos, </span></li> <li class=""><span class="comment">// Bytes to copy (that is, lastpos to this pos). </span><span> </span></li> <li class="alt"><span> BytesToCopy, </span></li> <li class=""><span class="comment">// The "running" result length, not the actual one. </span><span> </span></li> <li class="alt"><span> ResultLen, </span></li> <li class=""><span class="comment">// Length of aFindString, to save </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// calling LENGTH repetitively. </span><span> </span></li> <li class=""><span> FindLen, </span></li> <li class="alt"><span class="comment">// Length of aReplaceString, for the same reason. </span><span> </span></li> <li class=""><span> ReplaceLen, </span></li> <li class="alt"><span>SourceLen : Integer; </span></li> <li class=""><span class="comment">// This is where I explain the </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// TYPE TFastPosProc from earlier! </span><span> </span></li> <li class=""><span> FastPosProc : TFastPosProc; </span></li> <li class="alt"><span class="keyword">begin</span><span> </span></li> <li class=""><span> </span><span class="comment">//As this function has the option of being case-insensitive, I’d need to call </span><span> </span></li> <li class="alt"><span class="comment">// either FastPOS or FastPOSNoCase. The problem is that you’d have to do this </span><span> </span></li> <li class=""><span class="comment">// within a loop. This is a bad idea, since the result never changes throughou </span><span> </span></li> <li class="alt"><span class="comment">//t the whole operation–in which case we can determine it in advance, like so </span><span> </span></li> <li class=""><span class="comment">//: </span><span> </span></li> <li class="alt"><span> </span><span class="keyword">if</span><span> CaseSensitive </span><span class="keyword">then</span><span> </span></li> <li class=""><span> FastPosProc := FastPOS </span></li> <li class="alt"><span> </span><span class="keyword">else</span><span> </span></li> <li class=""><span> FastPOSProc := FastPOSNoCase; </span></li> <li class="alt"><span> </span><span class="comment">// I don't think I actually need </span><span> </span></li> <li class=""><span> </span><span class="comment">// this, but I don't really mind! </span><span> </span></li> <li class="alt"><span> Result := </span><span class="string">''</span><span>; </span></li> <li class=""><span> </span><span class="comment">// Get the lengths of the strings. </span><span> </span></li> <li class="alt"><span> FindLen := Length(aFindString); </span></li> <li class=""><span> ReplaceLen := Length(aReplaceString); </span></li> <li class="alt"><span> SourceLen := Length(aSourceString); </span></li> <li class=""><span> </span><span class="comment">// If we already have room for the replacements, </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// then set the length of the result to </span><span> </span></li> <li class=""><span> </span><span class="comment">// the length of the SourceString. </span><span> </span></li> <li class="alt"><span> </span><span class="keyword">if</span><span> ReplaceLen <= FindLen </span><span class="keyword">then</span><span> </span></li> <li class=""><span> ActualResultLen := SourceLen </span></li> <li class="alt"><span> </span><span class="keyword">else</span><span> </span></li> <li class=""><span> </span><span class="comment">// If not, we need to calculate the </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// worst-case scenario. </span><span> </span></li> <li class=""><span> </span><span class="comment">// That is, the Source consists ONLY of </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// aFindString, and we're going to replace </span><span> </span></li> <li class=""><span> </span><span class="comment">// every one of them! </span><span> </span></li> <li class="alt"><span> ActualResultLen := </span></li> <li class=""><span> SourceLen + </span></li> <li class="alt"><span> (SourceLen * ReplaceLen </span><span class="keyword">div</span><span> FindLen) + </span></li> <li class=""><span> ReplaceLen; </span></li> <li class="alt"><span> </span><span class="comment">// Set the length of Result; this </span><span> </span></li> <li class=""><span> </span><span class="comment">// will assign the memory, etc. </span><span> </span></li> <li class="alt"><span> SetLength(Result,ActualResultLen); </span></li> <li class=""><span> CurrentPos := </span><span class="number">1</span><span>; </span></li> <li class="alt"><span> ResultLen := </span><span class="number">0</span><span>; </span></li> <li class=""><span> LastPos := </span><span class="number">1</span><span>; </span></li> <li class="alt"><span> </span><span class="comment">//Again, I’m eliminating an IF statement in a loop by repeating code–this ap </span><span> </span></li> <li class=""><span class="comment">//proach results in very slightly larger code, but if ever you can trade some </span><span> </span></li> <li class="alt"><span class="comment">//memory in exchange for speed, go for it! </span><span> </span></li> <li class=""><span> </span><span class="keyword">if</span><span> ReplaceLen > </span><span class="number">0</span><span> </span><span class="keyword">then</span><span> </span><span class="keyword">begin</span><span> </span></li> <li class="alt"><span> </span><span class="keyword">repeat</span><span> </span></li> <li class=""><span> </span><span class="comment">// Get the position of the first (or next) </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// aFindString in aSourceString. </span><span> </span></li> <li class=""><span> </span><span class="comment">// Note that there's no If CaseSensitive, </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// I just call FastPOSProc, which is pointing </span><span> </span></li> <li class=""><span> </span><span class="comment">// to the correct pre-determined routine. </span><span> </span></li> <li class="alt"><span> CurrentPos := </span></li> <li class=""><span> FastPosProc(aSourceString, aFindString, </span></li> <li class="alt"><span> SourceLen, FindLen, CurrentPos); </span></li> <li class=""><span> </span><span class="comment">// If 0, then we're finished. </span><span> </span></li> <li class="alt"><span> </span><span class="keyword">if</span><span> CurrentPos = </span><span class="number">0</span><span> </span><span class="keyword">then</span><span> break; </span></li> <li class=""><span> </span><span class="comment">// Number of bytes to copy from the </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// source string is CurrentPos - lastPos, </span><span> </span></li> <li class=""><span> </span><span class="comment">// i.e. " cat " in "the cat the". </span><span> </span></li> <li class="alt"><span> BytesToCopy := CurrentPos-LastPos; </span></li> <li class=""><span> </span><span class="comment">// Copy chars from aSourceString </span><span> </span></li> <li class="alt"><span> </span><span class="comment">// to the end of Result. </span><span> </span></li> <li class=""><span> MyMove(aSourceString[LastPos], </span></li> <li class="alt"><span> Result[ResultLen+</span><span class="number">1</span><span>], BytesToCopy); </span></li> <li class=""><span> </span><span class="comment">// Copy chars  相关文章 Golang 汇编入门知识总结 未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序 视频防盗链技术方案研究与讲解 Visual Studio Code 无法执行tsc编译ts文件的解决办法 JavaScript Array 数组常用函数 汇编指令大全 mysql笔记(5)--集合函数,时间日期函数,字符串匹配函数 SQL自定义函数实现特殊功能 Delphi常用的函数库 批量快速查找替换文件内容 Advanced Find and Replace Last modification:August 16th, 2009 at 12:30 pm © 允许规范转载 Support 如果觉得我的文章对你有用,请随意赞赏 ×Close Appreciate the author Sweeping payments Pay by AliPay Pay by WeChat