Delphi XE2 Assembly
-
26-10-2019 - |
Frage
Ich habe die folgende Funktion, die in Delphi 2006 funktioniert, jedoch unter Delphi XE2 entweder einen Zugriffsverletzungsfehler oder einen privilegierten Anweisungsfehler bei der Verarbeitung enthält 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;
Ich kenne die Versammlung nicht sehr gut. Was ist das Problem?
Lösung
Ich stimme Davids Vorschlag voll und ganz zu, dies einfach in Pascal zu codieren und diese Antwort aufzunehmen. Wenn die Profilierung nicht darauf hingewiesen hat, dass dies ein echter Engpass ist, ist es wirklich nicht erforderlich, dass die ASM. Hier sind zwei Versionen. Das erste ist einfacher zu lesen, aber der zweite ist effizienter:
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;
Andere Tipps
Delphi 2006 verwendet einzelne Byte -ANSI -Zeichen usw. string
ist AnsiString
, Char
ist AnsiChar
. Auf Delphi 2009 und später werden zwei Byte -Unicode -Zeichen verwendet. Diese Funktion kann unmöglich bei beiden Compilern funktionieren.
Sogar der Standard -Hack der Verwendung von Ansistring und Ansichar funktioniert nicht. Höchstwahrscheinlich sind die Annahmen, die diese Funktion über die RTL -Implementierung macht, im modernen Delphi nicht mehr gültig.
Ich würde diese Funktion in Pascal neu schreiben und den Compiler die Arbeit erledigen lassen. Dies wird nicht nur der schnellste Weg sein, um Ihr aktuelles Problem zu lösen, sondern auch die Hürde von 64-Bit-Zusammenstellung, wenn Sie sich jemals dafür entscheiden, dies zu bekämpfen.