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?

War es hilfreich?

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top