简体   繁体   English

Delphi XE2组装

[英]Delphi XE2 assembly

I have the following function that works in Delphi 2006, but under Delphi XE2 it gives either an access violation error or a privileged instruction error when processing RET . 我有以下功能在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;

I don't know assembly very well. 我不太了解装配。 What is the problem? 问题是什么?

I completely agree with David's suggestion to simply code this in Pascal and have upvoted that answer. 我完全同意David的建议,只需在Pascal中对此进行编码并对该答案进行投票。 Unless profiling has indicated that this is a true bottleneck then there's really no need for the ASM. 除非分析表明这是一个真正的瓶颈,否则实际上不需要ASM。 Here are two versions. 这是两个版本。 The first is easier to read but the second is more efficient: 第一个更容易阅读,但第二个更有效:

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;

Delphi 2006 uses single byte ANSI characters and so string is AnsiString , Char is AnsiChar . Delphi 2006使用单字节ANSI字符,因此stringAnsiStringCharAnsiChar On Delphi 2009 and later, two byte Unicode characters are used. 在Delphi 2009及更高版本中,使用了两个字节的Unicode字符。 This function cannot possibly work on both compilers. 此函数不可能在两个编译器上都有效。

Even the standard hack of using AnsiString and AnsiChar does not work. 即使使用AnsiString和AnsiChar的标准黑客也行不通。 Most likely the assumptions that this function makes about the RTL implementation are no longer valid in modern Delphi. 很可能这个函数对RTL实现的假设在现代Delphi中不再有效。

I would re-write this function in Pascal and let the compiler do the work. 我会在Pascal中重写这个函数,让编译器完成这项工作。 Not only will that be the quickest way to solve your current problem, it will also get you over the hurdle of 64-bit compilation should you ever choose to tackle that. 这不仅是解决当前问题的最快方法,如果您选择解决这个问题,它也会让您超越64位编译的障碍。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM