5

私が継承した最近のDelphiプロジェクトには、ASMにプロシージャがあります。私は完全なASM初心者なので、理解できません。プロシージャフローを解読するためにさまざまなASM命令を読みましたが、それでもわかりません。

ASMの経験がある人が私の理解を助け、次の手順を英語に翻訳できますか(その後、Delphiに翻訳し直して、コードが将来読みやすくなります!!!)

Mem1の宣言は、バイトの配列[0..15]です。。そして、Mem2はLongIntです。

手順は次のとおりです。

 procedure TForm1.XorMem(var Mem1; const Mem2; Count : Cardinal); register;
 begin
 asm
   push esi
   push edi

   mov  esi, eax         //esi = Mem1
   mov  edi, edx         //edi = Mem2

   push ecx              //save byte count
   shr  ecx, 2           //convert to dwords
   jz   @Continue

   cld
 @Loop1:                 //xor dwords at a time
   mov  eax, [edi]
   xor  [esi], eax
   add  esi, 4
   add  edi, 4
   dec  ecx
   jnz  @Loop1

 @Continue:              //handle remaining bytes (3 or less)
   pop  ecx
   and  ecx, 3
   jz   @Done

 @Loop2:                 //xor remaining bytes
   mov  al, [edi]
   xor  [esi], al
   inc  esi
   inc  edi
   dec  ecx
   jnz  @Loop2

 @Done:
   pop  edi
   pop  esi
 end;

 end;

編集:Roman Rのおかげで、ASMをDelphiに戻しました

procedure TForm1.XorMem2(var Mem1; const Mem2 :LongInt; Count : Cardinal);
var
  Key : array [0..3] of byte absolute Mem1;
  Num : array [0..3] of byte absolute Mem2;
  idx : byte;
begin
  for Idx := 0 to Count -1 do Key[idx] := Key[idx] Xor Num[idx];
end;
4

2 に答える 2

8

この関数は、2つのポインター(配列に関係なく)とその長さ(バイト単位)を受け入れます。XORこの関数は、2番目の配列バイト(Mem2)を使用して、最初の配列バイト(Mem1)に対してバイトツーバイト演算を実行します。擬似コード:

for Index = 0 to Count - 1
  (Mem1 as Byte Array) [Index] = (Mem1 as Byte Array) [Index] Xor (Mem2 as Byte Array) [Index]
于 2011-10-25T05:56:35.977 に答える
4

これが機能するシンプルな純粋なパスカルバージョンです。

procedure TForm1.XorMem(var Mem1; const Mem2; Count : Cardinal);
var i: integer;
    M1: TByteArray absolute Mem1;
    M2: TByteArray absolute Mem2;
begin
  for i := 0 to Count-1 do
     M1[i] := M1[i] xor M2[i];
end;

これは、DWORD読み取りを使用して最適化されたバージョンです。

procedure TForm1.XorMem(var Mem1; const Mem2; Count : Cardinal);
var i, n: integer;
    M1: TByteArray absolute Mem1;
    M2: TByteArray absolute Mem2;
    I1: TIntegerArray absolute Mem1;
    I2: TIntegerArray absolute Mem2;
begin
  n := Count shr 2;
  for i := 0 to n-1 do
     I1[i] := I1[i] xor I2[i];
  n := n shl 2;
  for i := 0 to (Count and 3)-1 do
     M1[n+i] := M1[n+i] xor M2[n+i];
end;

IMHOの2番目のバージョンは必須ではありません。データがDWORDにアラインされている場合、DWORDを一度に読み取ることは理にかなっています。そうしないと、効果的に遅くなる可能性があります。少量のデータの場合、小さなDelphiループは十分に高速で、読みやすくなります。最新のCPU(Core i5やi7など)は、小さなコードループを使用するときに不思議に思います(ループを展開する必要はもうありません)。

于 2011-10-25T12:58:42.570 に答える