Ensamblaje de Delphi XE2
-
26-10-2019 - |
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?
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.