Delphi XE2 в сборе - PullRequest
       37

Delphi XE2 в сборе

3 голосов
/ 17 февраля 2012

У меня есть следующая функция, которая работает в Delphi 2006, но в Delphi XE2 она выдает либо ошибку нарушения доступа, либо ошибку привилегированной инструкции при обработке 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;

Я не очень хорошо знаю сборку. В чем проблема?

Ответы [ 2 ]

17 голосов
/ 17 февраля 2012

Я полностью согласен с предложением Дэвида просто закодировать это на Паскале и проголосовал за этот ответ. Если профилирование не указывает на то, что это действительно узкое место, то в ASM нет никакой необходимости. Вот две версии. Первое легче читать, а второе более эффективно:

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;
6 голосов
/ 17 февраля 2012

Delphi 2006 использует однобайтовые символы ANSI, поэтому string равно AnsiString, Char равно AnsiChar. В Delphi 2009 и более поздних версиях используются двухбайтовые символы Unicode. Эта функция не может работать на обоих компиляторах.

Даже стандартный взлом AnsiString и AnsiChar не работает. Скорее всего, предположения, которые эта функция делает относительно реализации RTL, больше не действительны в современном Delphi.

Я бы переписал эту функцию на Паскале и позволил компилятору сделать всю работу. Это не только самый быстрый способ решения текущей проблемы, но и преодоление препятствия 64-битной компиляции, если вы когда-нибудь решите эту проблему.

...