2012-02-17 29 views
3

私はDelphi 2006で動作する以下の機能を持っていますが、Delphi XE2では、RETの処理時にアクセス違反エラーまたは特権命令エラーが発生します。Delphi XE2アセンブリ

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 [email protected] 
     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 [email protected] 
     POP  ESI 
end; 

私はアセンブリがよく分かりません。何が問題ですか?

+1

ところで、このasmコードはちょっとひどくコード化されています。たとえば、sの文字列がChの1つの文字だけであれば、AV、IMHOを作成します。それを忘れて、Mikeが提供した2番目のパスカル版を彼の答えに使用してください。 –

+1

これは非常に狭義に定義されているので、私は投票に投票しました。誰かがそれに確実に答えたように見えるのは印象的ですが、サイトに対するこのような質問の価値はゼロに似ています。 –

答えて

17

私はデイビッドの示唆に完全に同意しています。これはパスカルでこれをコード化し、その答えをアップアップしました。プロファイリングがこれが真のボトルネックであることを示していない限り、ASMは本当に必要ありません。ここに2つのバージョンがあります。最初は読みやすく、2番目の方が効率的です。

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; 
+1

+1はコードが実際に何をしたのかで動作します。 2番目のバージョンが優れています。明らかな最適化は、First = 1とLast = Length(S)のときにcopyを呼び出さないことです。 –

+0

+1。複雑なコンパイラ生成の文字列操作ルーチンは、特にこのような単純なケースでは、うまくいきません。私は元のアセンブラがここで提供された2番目のパスカル変種より速いとは思わない! –

+0

@CosminPrund 2番目のバージョンはオリジナルのasmバージョンよりもバグが少なく、同じバージョンを実行します.IMHOのバージョンがバグだった(たとえば 'S = Ch'の場合)。真に最適化されたasmバージョンのクローズアルゴリズムについては、[this unit](http://synopse.info/fossil/finfo?name=SynCommons)のasmとpascalの両方で 'function Trim(const S:RawUTF8):RawUTF8; .pas) - Delphi 2009/2010/XE/XE2用に変更されたJohn O'Harrowのアセンブラを使用しました。 –

6

Delphi 2006では1バイトのANSI文字が使用されているため、stringAnsiString,CharAnsiCharです。 Delphi 2009以降では、2バイトのUnicode文字が使用されています。この関数は両方のコンパイラではうまく動作しません。

AnsiStringとAnsiCharを使用する標準的なハックは機能しません。ほとんどの場合、この関数がRTL実装について行う前提は、現代のDelphiでは有効ではありません。

私はこの関数をPascalに書き直し、コンパイラに作業を任せます。それがあなたの現在の問題を解決する最速の方法であるだけでなく、64ビットコンパイルの障害を乗り越えて、それに取り組むことを選択してください。

+1

downvoterさんがコメントしますか? –

+2

提供されたコードの主な問題は文字列/ AnsiStringの問題ではなく、asm全体がブロックされています。これはx64で動作しません。これは、さまざまなレジスタレイアウトと* LStrFromPCharLen API Delphi 2009以降。 –

+1

@Arnaud私はその批判がやや弱いと感じます。 x64はポイントの横にあります。 OPは確かに32ビットをコンパイルしています。そのコードは32ビットXE2では動作しません。また、32ビットの2010またはXEでは動作しません。プラス私はx64ビットにコメントしたので、私はそれをカバーしていた。そして、主要な問題については、私はそれを全く買わない。コードに問題があると、それはうまく動作しません。したがって、コードには複数の欠陥があります。答えがすべての単一の問題を識別するのに失敗した場合、それはdownvoteの価値があるようになりますか?盲目的に明らかな結論は、パスカル変換が必要であるということです。破損したコードを過度に分析する必要はありません。 –

関連する問題