ترجمة رمز باستخدام المؤشر ، إلى التجميع في Pascal - Delphi

StackOverflow https://stackoverflow.com/questions/2173570

سؤال

لدي هذا الرمز أدناه ، وأريد ترجمته إلى ASM ، لاستخدامه في Delphi أيضًا.

var
    FunctionAddressList: Array of Integer;

type TFunction = function(parameter: Integer): Integer; cdecl;

function Function(parameter: Integer): Integer;
var
    ExternFunction: TFunction;
begin
    ExternFunction := TFunction(FunctionAddressList[5]);
    Result := ExternFunction(parameter);
end;

إنه يعمل بشكل طبيعي ، لكن عندما أجرب نسخة التجميع:

function Function(parameter: Integer): Integer; cdecl;
asm
  mov eax, FunctionAddressList
  jmp dword ptr [eax + 5 * 4]
end;

من المفترض أن تعمل ، لأنه في C ++ يعمل في كلا الاتجاهين:

void *FunctionAddressList;

_declspec(naked) int Function(int parameter)
{
    _asm mov eax, FunctionAddressList;
    _asm jmp dword ptr [eax + 5 * 4];
}

typedef int (*TFunction)(int parameter);
int Function(int parameter)
{
    TFunction ExternFunction = ((TFunction *)FunctionAddressList)[5];
    return ExternFunction(parameter);
}

لكنه لا يعمل في دلفي.

في إصدار التجميع ، يضاعف الصفيف إلى 4 ، لأنه حجم الإزاحة بين كل عنصر من عناصر الصفيف ، وبالتالي فإن كلا الإصدارين متكافئان.

لذلك ، أريد أن أعرف لماذا لا يعمل مع دلفي. في دلفي ، يختلف حجم الإزاحة بين قيم عدد صحيح في صفيف عن C ++؟

لقد جربت بالفعل العديد من التعويضات ، مثل 1 ، 2 ، 4 ، 6 ، 8 ، وما إلى ذلك ، وأنواع كثيرة من الصفيف (مجموعة من المؤشر ؛ مؤشر فقط ؛ مجموعة من عدد صحيح ، إلخ) ، وحاولت العديد من اتفاقيات الاتصال ، وكان CDECL هو الوحيد الذي عمل مع الإصدار غير ASM ، ولكن مع ASM ، لم تنجح جميع الاختبارات.

شكرًا.

هل كانت مفيدة؟

المحلول

أول تطبيق اختبار لإعادة إنتاج الخطأ:

var
  FunctionAddressList: Array of Integer;

function Bar(parameter: Integer): Integer; cdecl;
begin
  ShowMessage('Bar '+IntToStr(parameter));
end;

function Foo(parameter: Integer): Integer; cdecl;
asm
  mov eax, FunctionAddressList
  jmp dword ptr [eax + 5 * 4]
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SetLength(FunctionAddressList, 6);
  FunctionAddressList[5]:= Integer(@Bar);
  Foo(25);
end;

يتم تعريف عنوان الشريط بشكل صحيح ، ولكن المشكلة هي أن برنامج التحويل البرمجي Delphi يولد مقدمة و epilog لـ Foo ، لذا فإن رمز FOO الحقيقي هو

0046CD30 55               push ebp
0046CD31 8BEC             mov ebp,esp
Unit1.pas.46:             mov eax, FunctionAddressList
Unit1.pas.47:             jmp dword ptr [eax + 5 * 4]
0046CD3B 5D               pop ebp
0046CD3C C3               ret

نتيجةً لذلك ، تالف المكدس ، والمعلمة خاطئة وعنوان الإرجاع الشريطي خاطئ. إذا كنت لا تزال ترغب في القيام بالخدعة ، فاستخدم

function Foo(parameter: Integer): Integer; cdecl;
asm
  pop ebp
  mov eax, FunctionAddressList
  jmp dword ptr [eax + 5 * 4]
end;

نصائح أخرى

Array of Integer ليس ما تعتقد أنه. إنها صفيف ديناميكي يديره تلقائيًا.

يجب أن تجرب نفس الشيء باستخدام FunctionAddressList: ^Pointer; - لاحظ أنه سيتعين عليك القيام بتخصيص يدوي وتخصيص.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top