دالة تجميع دلفي تقوم بإرجاع سلسلة طويلة
سؤال
أحاول أن أتعلم برمجة التجميع المضمنة في دلفي، وتحقيقا لهذه الغاية وجدت هذا المقال مفيدة للغاية.
الآن أرغب في كتابة دالة تجميع ترجع سلسلة طويلة، على وجه التحديد AnsiString
(للبساطة).لقد كتبت
function myfunc: AnsiString;
asm
// eax = @result
mov edx, 3
mov ecx, 1252
call System.@LStrSetLength
mov [eax + 0], ord('A')
mov [eax + 1], ord('B')
mov [eax + 2], ord('C')
end;
توضيح:
الدالة التي تُرجع سلسلة لها قيمة غير مرئية var result: AnsiString
(في هذه الحالة) المعلمة، لذلك، في بداية الوظيفة، eax
يجب أن يحمل عنوان السلسلة الناتجة.ثم قمت بتعيين edx
و ecx
إلى 3 و1252 على التوالي، ثم اتصل System._LStrSetLength
.في الواقع، أنا أفعل
_LStrSetLength(@result, 3, 1252)
حيث 3 هو الطول الجديد للسلسلة (بالأحرف = البايت) و1252 هو الطول القياسي ويندوز-1252 صفحة الرموز.
ثم معرفة ذلك eax
يكون عنوان الحرف الأول من السلسلة, ، لقد قمت ببساطة بتعيين السلسلة على "ABC".لكنه لا يعمل - إنه يعطيني بيانات غير منطقية أو EAccessViolation.ما المشكلة؟
تحديث
الآن لدينا تطبيقان يعملان على ما يبدو myfunc
, ، توظيف واحد NewAnsiString
وتوظيف واحد LStrSetLength
.لا يسعني إلا أن أتساءل عما إذا كان كلاهما صحيحًا، بمعنى أنهما لا يفسدان معالجة دلفي الداخلية للسلاسل (العد المرجعي، والتحرير التلقائي، وما إلى ذلك).
المحلول
يجب عليك استخدام نوع من:
function myfunc: AnsiString;
asm
push eax // save @result
call system.@LStrClr
mov eax,3 {Length}
{$ifdef UNICODE}
mov edx,1252 // code page for Delphi 2009/2010
{$endif}
call system.@NewAnsiString
pop edx
mov [edx],eax
mov [eax],$303132
end;
سيعود سلسلة "210" ...
ومن الجيد دائمًا وضع كتلة {$ifdef UNICODE} لجعل الكود الخاص بك متوافقًا مع إصدار دلفي قبل عام 2009.
نصائح أخرى
بمساعدة ممتازة من A.Bouchez، تمكنت من تصحيح الكود الخاص بي، باستخدام LStrSetLength
:
function myfunc: AnsiString;
asm
push eax
// eax = @result
mov edx, 3
mov ecx, 1252
call System.@LStrSetLength
pop eax
mov ecx, [eax]
mov [ecx], 'A'
mov [ecx] + 1, 'B'
mov [ecx] + 2, 'C'
end;