Перевести стиль Delphi ASM на английский? - PullRequest
5 голосов
/ 25 октября 2011

В недавнем проекте 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;

edit: Благодаря Роману 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;

Ответы [ 2 ]

8 голосов
/ 25 октября 2011

Функция принимает два указателя (для любых массивов) и их длины в байтах. Функция выполняет побайтовую XOR операцию с байтами первого массива (Mem1), используя байты второго массива (Mem2). Псевдо-код:

for Index = 0 to Count - 1
  (Mem1 as Byte Array) [Index] = (Mem1 as Byte Array) [Index] Xor (Mem2 as Byte Array) [Index]
4 голосов
/ 25 октября 2011

Вот рабочая и простая версия на чистом паскале:

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;

ИМХО 2-я версия не обязательна. Чтение DWORD сразу имеет смысл, если данные выровнены по DWORD. В противном случае, это может быть эффективно медленнее. Для небольшого объема данных небольшой цикл Delphi будет достаточно быстрым и понятным для чтения. Последние процессоры (например, Core i5 или i7) творят чудеса, когда используют небольшой цикл кода (развертывание цикла больше не требуется).

...