Reputation: 1796
I have the following function that works in Delphi 2006, but under Delphi XE2 it gives either an access violation error or a privileged instruction error when processing RET
.
function Q_TrimChar(const S: string; Ch: Char): string;
asm
PUSH ESI
MOV ESI,ECX
TEST EAX,EAX
JE @@qt
MOV ECX,[EAX-4]
TEST ECX,ECX
JE @@qt
PUSH EBX
PUSH EDI
MOV EBX,EAX
MOV EDI,EDX
XOR EDX,EDX
MOV EAX,ESI
CALL System.@LStrFromPCharLen
MOV EDX,EDI
MOV ECX,[EBX-4]
@@lp1: CMP DL,BYTE PTR [EBX]
JNE @@ex1
INC EBX
DEC ECX
JNE @@lp1
MOV EDX,[ESI]
JMP @@wq
@@ex1: DEC ECX
@@lp2: CMP DL,BYTE PTR [EBX+ECX]
JNE @@ex2
DEC ECX
JMP @@lp2
@@ex2: MOV EDI,[ESI]
LEA EDX,[EDI+ECX+1]
@@lp3: MOV AL,BYTE PTR [EBX+ECX]
MOV BYTE PTR [EDI+ECX],AL
DEC ECX
JNS @@lp3
@@wq: MOV EAX,[ESI]
MOV BYTE PTR [EDX],0
SUB EDX,EAX
MOV [EAX-4],EDX
POP EDI
POP EBX
POP ESI
RET
@@qt: MOV EAX,ESI
CALL System.@LStrClr
POP ESI
end;
I don't know assembly very well. What is the problem?
Upvotes: 3
Views: 1751
Reputation: 613013
Delphi 2006 uses single byte ANSI characters and so string
is AnsiString
, Char
is AnsiChar
. On Delphi 2009 and later, two byte Unicode characters are used. This function cannot possibly work on both compilers.
Even the standard hack of using AnsiString and AnsiChar does not work. Most likely the assumptions that this function makes about the RTL implementation are no longer valid in modern Delphi.
I would re-write this function in Pascal and let the compiler do the work. Not only will that be the quickest way to solve your current problem, it will also get you over the hurdle of 64-bit compilation should you ever choose to tackle that.
Upvotes: 6
Reputation: 1284
I completely agree with David's suggestion to simply code this in Pascal and have upvoted that answer. Unless profiling has indicated that this is a true bottleneck then there's really no need for the ASM. Here are two versions. The first is easier to read but the second is more efficient:
function Q_TrimChar(const S: string; Ch: Char): string;
begin
result := S;
while (result <> '') and (result[1] = Ch) do Delete(Result, 1, 1);
while (result <> '') and (result[Length(Result)] = Ch) do Delete(Result, Length(Result), 1);
end;
function Q_TrimChar(const S: string; Ch: Char): string;
var
First, Last : integer;
begin
First := 1;
Last := Length(S);
while (First < Last) and (S[First] = Ch) do inc(First);
while (Last >= First) and (S[Last] = Ch) do Dec(Last);
Result := copy(S, First, Last-First+1);
end;
Upvotes: 17