Delphi XE2组装

The*_*oon 3 delphi assembly delphi-2006 delphi-xe2 basm

我有以下功能在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;
Run Code Online (Sandbox Code Playgroud)

我不太了解装配.问题是什么?

Mik*_*e W 17

我完全同意David的建议,只需在Pascal中对此进行编码并对该答案进行投票.除非分析表明这是一个真正的瓶颈,否则实际上不需要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;
Run Code Online (Sandbox Code Playgroud)


Dav*_*nan 6

德尔福2006年使用单字节ANSI字符等等string就是AnsiString,Char就是AnsiChar.在Delphi 2009及更高版本中,使用了两个字节的Unicode字符.此函数不可能在两个编译器上都有效.

即使使用AnsiString和AnsiChar的标准黑客也行不通.很可能这个函数对RTL实现的假设在现代Delphi中不再有效.

我会在Pascal中重写这个函数,让编译器完成这项工作.这不仅是解决当前问题的最快方法,如果您选择解决这个问题,它也会让您超越64位编译的障碍.

  • 提供的代码中的主要问题绝对不是关于字符串/ AnsiString问题,而是整个asm块本身,由于各种寄存器布局*和*LStrFromPCharLen` API的新签名,因此在x64中根本不起作用.德尔福2009. (2认同)