p; mov ESI, aFindString mov ECX, SourceLen Mov Al, [ESI]
//add by shengquanhu:just modified the lowercase ''''a''''..''''z'''' cmp Al, $7A ja @ScaSB
cmp Al, $61 jb @ScaSB //end------------------------------------------
// Make Al uppercase. and Al, $df
@ScaSB: Mov Ah, [EDI]
//add by shengquanhu:just modified the lowercase ''''a''''..''''z'''' cmp Ah, $7A ja @CompareChar
cmp Ah, $61 jb @CompareChar //end------------------------------------------
// Make Ah uppercase. and Ah, $df
@CompareChar: cmp Ah,Al jne @NextChar @CompareStrings: mov EBX, aFindLen dec EBX
//add by ShengQuanhu Jz @EndOfMatch //add end
@CompareNext: mov Al, [ESI+EBX] mov Ah, [EDI+EBX]
//add by shengquanhu:just modified the lowercase ''''a''''..''''z'''' cmp Ah, $7A ja @LowerAh
cmp Al, $61 jb @LowerAh //end------------------------------------------
// Make Al and Ah uppercase. and Al, $df
//add by shengquanhu:just modified the lowercase ''''a''''..''''z'''' @LowerAh: cmp Ah, $7A ja @CompareChar2
cmp Ah, $61 jb @CompareChar2 //end------------------------------------------
and Ah, $df
@CompareChar2: cmp Al, Ah Jz @Matches Mov Al, [ESI]
//add by shengquanhu:just modified the lowercase ''''a''''..''''z'''' cmp Al, $7A ja @NextChar
cmp Al, $61 jb @NextChar //end------------------------------------------
// Make Al uppercase. and Al, $df Jmp @NextChar @Matches: Dec EBX Jnz @CompareNext
//add by Shengquanhu @EndOfMatch: //add end
mov EAX, EDI sub EAX, aSourceString inc EAX mov Result, EAX jmp @TheEnd @NextChar: Inc EDI dec ECX //add by shengquanhu //if ah is chinese char,jump again jz @Result0 cmp ah, $80 jb @ScaSB Inc EDI Dec ECX //add by shengquanhu end jnz @ScaSB @Result0: mov Result,0 @TheEnd: pop EBX pop EDI pop ESI end; end;
//My move isn’t as fast as MOVE when source and destination are both DWord al //igned, but it’s certainly faster when they’re not. As we’re moving charac //ters in a string, it isn’t very likely at all that both source and destinat //ion are DWord aligned, so moving bytes avoids the cycle penalty of reading/w //riting DWords across physical boundaries. procedure MyMove( const Source; var Dest; Count : Integer); asm // Note: When this function is called, // Delphi passes the parameters as follows: // ECX = Count // EAX = Const Source // EDX = Var Dest // If there are no bytes to copy, just quit // altogether; there''''s no point pushing registers. cmp ECX,0 Je @JustQuit // Preserve the critical Delphi registers. push ESI push EDI // Move Source into ESI (generally the // SOURCE register). // Move Dest into EDI (generally the DEST // register for string commands). // This might not actually be necessary, // as I''''m not using MOVsb etc. // I might be able to just use EAX and EDX; // there could be a penalty for not using // ESI, EDI, but I doubt it. // This is another thing worth trying! mov ESI, EAX mov EDI, EDX // The following loop is the same as repNZ // MovSB, but oddly quicker! @Loop: // Get the source byte. Mov AL, [ESI] // Point to next byte. Inc ESI // Put it into the Dest. mov [EDI], AL // Point dest to next position. Inc EDI // Dec ECX to note how many we have left to copy. Dec ECX // If ECX <> 0, then loop. Jnz @Loop // Another optimization note. // Many people like to do this. // Mov AL, [ESI] // Mov [EDI], Al // Inc ESI // Inc ESI //There’s a hidden problem here. I won’t go into too much detail, but the Pe //ntium can continue processing instructions while it’s still working out the // result of INC ESI or INC EDI. If, however, you use them while they’re stil //l being calculated, the processor will stop until they’re calculated (a pen //alty). Therefore, I alter ESI and EDI as far in advance as possible of using // them. // Pop the critical Delphi registers // that we''''ve altered. pop EDI pop ESI @JustQuit: end;
//Point 1: I pass VAR aSourceString rather than just aSourceString. This is be //cause I’ll just be passed a pointer to the data rather than a 10M copy of t //he data itself, which is much quicker! function FastReplace( var aSourceString : String; const aFindString, aReplaceString : String; CaseSensitive : Boolean = False) : String; var // Size already passed to SetLength, // the REAL size of RESULT. ActualResultLen, // Position of aFindString is aSourceString. CurrentPos, // Last position the aFindString was found at. LastPos, // Bytes to copy (that is, lastpos to this pos). BytesToCopy, // The "running" result length, not the actual one. ResultLen, // Length of aFindString, to save // calling LENGTH repetitively. FindLen, // Length of aReplaceString, for the same reason. ReplaceLen, SourceLen : Integer; // This is where I explain the // TYPE TFastPosProc from earlier! FastPosProc : TFastPosProc; begin //As this function has the option of being case-insensitive, I’d need to call // either FastPOS or FastPOSNoCase. The problem is that you’d have to do this // within a loop. This is a bad idea, since the result never changes throughou //t the whole operation–in which case we can determine it in advance, like so //: if CaseSensitive then FastPosProc := FastPOS else FastPOSProc := FastPOSNoCase; // I don''''t think I actually need // this, but I don''''t really mind! Result := ''''''''; // Get the lengths of the strings. FindLen := Length(aFindString); ReplaceLen := Length(aReplaceString); SourceLen := Length(aSourceString); // If we already have room for the replacements, // then set the length of the result to // the length of the SourceString. if ReplaceLen <= FindLen then ActualResultLen := SourceLen else // If not, we need to calculate the // worst-case scenario. 上一页 [1] [2] [3] 下一页 |