Pregunta

Tengo la siguiente función que funciona en Delphi 2006, pero bajo Delphi XE2 ofrece un error de violación de acceso o un error de instrucción privilegiado al procesar 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;

No conozco muy bien la asamblea. ¿Cuál es el problema?

¿Fue útil?

Solución

Estoy completamente de acuerdo con la sugerencia de David de simplemente codificar esto en Pascal y he votado esa respuesta. A menos que el perfil haya indicado que este es un verdadero cuello de botella, entonces realmente no hay necesidad de la ASM. Aquí hay dos versiones. El primero es más fácil de leer, pero el segundo es más eficiente:

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;

Otros consejos

Delphi 2006 usa caracteres de byte ANSI y así string es AnsiString, Char es AnsiChar. En Delphi 2009 y más tarde, se utilizan dos caracteres de Byte Unicode. Esta función no puede funcionar en ambos compiladores.

Incluso el truco estándar de usar Ansistring y Ansichar no funciona. Lo más probable es que las suposiciones que realice esta función sobre la implementación RTL ya no sean válidas en Delphi moderna.

Reescribiría esta función en Pascal y dejaría que el compilador haga el trabajo. No solo será la forma más rápida de resolver su problema actual, sino que también lo superará por el obstáculo de la compilación de 64 bits si alguna vez elige abordar eso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top