2012-05-16 20 views
5

Yapmak istediğim, derleme kullanarak bir sınıf örneği oluşturmak, yöntemlerinden birini çağırmak ve sonra örneği boşaltmak.Delphi satır içi assembler'ı kullanarak sınıf örneği oluşturma

Çok önemli ve muhtemelen çok basit bir şeyi kaçırdığımı biliyorum, ama ne olduğunu bilmiyorum.

program Project2; 

{$APPTYPE CONSOLE} 

uses 
    SysUtils; 

type 
    TSomeClass = class(TObject) 
    private 
    FCreateDateTime: string; 
    public 
    constructor Create; 
    procedure SayYeah; 
    end; 

constructor TSomeClass.Create; 
begin 
    FCreateDateTime := DateTimeToStr(Now); 
end; 

procedure TSomeClass.SayYeah; 
begin 
    Writeln('yeah @ ' + FCreateDateTime); 
end; 

procedure Doit; 
asm 
    CALL TSomeClass.Create; // <= Access Violation 
    CALL TSomeClass.SayYeah; 
    CALL TSomeClass.Free; 
end; 

begin 
    try 
    Doit; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    Readln; 
end. 

Bilginize: Ben bunu yapmanın başka bir yolu, düşük seviyede bunu başarmak nasıl anlamak istiyorum.

GÜNCELLEME: ziyade PUSH daha Ebx kullanılarak kusur bulmak için Arnaud için

Teşekkür:

Update2: Andreas Rejbrand için

sayesinde, suçlu bulmak başardınız/POP EAX

var 
    TSomeClass_TypeInfo: Pointer; 

procedure Doit; 
asm 
    MOV DL, $01; 
    MOV EAX, TSomeClass_TypeInfo; 
    CALL TSomeClass.Create; 
    PUSH EAX; 
    CALL TSomeClass.SayYeah; // call method 
    POP EAX; 
    MOV DL, $01; 
    CALL TSomeClass.Free; // pointer to instance(Self) is expected in EAX 
end; 

begin 
    TSomeClass_TypeInfo := TSomeClass; 
    try 
    Doit; 
    except 
    on E: Exception do 
     Writeln(E.ClassName, ': ', E.Message); 
    end; 
    Readln; 
end. 
+1

EBX'in kaydedilmesi gerekiyor - Arnaud'un cevabına bir göz atmalısın – PhiS

+0

@PhiS evet Efendim, Arnaud'un cevabını okudum, kiminle ilgileniyorsa, tüm cevapları okuyacak (sadece 2) ve yorumlar (: – ComputerSaysNo

+0

EBX'i kaydetmeden kullandığınız soruyu güncellemenizde, lütfen bunu düzeltin (örn. ebx/pop ebx komutunu kullanın), eğer böyle bir işlevi kullanan gerçek bir programın çökmesine neden olmuyorsanız - ve bunun nedeni bulmak çok zor olurdu ... – PhiS

cevap

2

Bunu bir konuda okuyabilirsiniz. n Delphi montaj programı için mükemmel kılavuz, aslında here bulunmuştur. Ne yazık ki, site çöktü, ancak arşivlenmiş bir sürüm here bulabilirsiniz. Özellikle page 5'a bakın.

+0

+1 ve kabul, çok teşekkür ederim! – ComputerSaysNo

+0

Bu teorik soruya cevap verebilirken, biz dahil etmenizi isteriz cevabınızdaki bağlantılı makalenin önemli kısımları ve [referans için bağlantı] sağlayın (http://meta.stackexchange.com/q/8259). bağlantı çürümesi riski. – Kev

+3

@Kev: Bunun tam olarak farkındayım ve bu cevabın sadece talep edilmesinden sonra gönderilmesinin sebebi buydu. Aslında, sadece bir yorum olarak bağlantıyı verdim, ancak bu artık belli değil (yorumlarınızı sildiniz). Maalesef, bağlandığım sayfadaki konuları öğrenmek için şu anda zamanım/enerjim yok. –

10

Asm kodunuz doğru değil.

Korunması gereken ebx kaydına aşırı yüklüyorsunuz. Ve global değişken trick mantıklı değil.

procedure Doit(ClassType: pointer); 
asm // eax=TList 
    mov dl,true // hidden boolean 2nd parameter 
    call TObject.Create 
    push eax 
    call TList.Pack 
    pop eax 
    call TObject.Free 
end; 

DoIt(TList); 

Ama try...finally ile örneğini korumaz:

Daha iyi bir kodlama olmalıdır. :) mov dl,true parametre Hakkında

, this official page from the EMB wiki bkz:

Kurucular ve yıkıcılar ek Boole bayrağı parametresi geçirilir dışında diğer yöntemler olarak aynı arama kuralları kullanmak yapıcı bağlamını belirtir veya yıkıcı çağrı.

yapıcı aramanın bayrak parametresi Yanlış değeri yapıcı bir örnek nesnesi üzerinden çağrılan ya da kalıtsal anahtar kelimeyi kullanarak belirtir. Bu durumda, kurucu bir olağan yöntem gibi davranır. yapıcı çağrısının bayrak parametresindeki True değeri, kurucunun bir sınıf başvurusu aracılığıyla çağrıldığını gösterir. Bu durumda, yapıcı, Self tarafından verilen sınıfı örneğini oluşturur ve EAX'te yeni oluşturulan nesnesine bir başvuru döndürür.

Bir destructor çağrısının flag parametresindeki bir False değeri, yıkıcı tarafından devralınan anahtar sözcük kullanılarak çağrılan gösterir. Bu durumunda, yıkıcı sıradan bir yöntem gibi davranır. Bir yıkıcı aramanın flag parametresinde True değeri, bir örnek nesnesi aracılığıyla yıkıcısının çalıştırıldığını gösterir.Bu durumda, destructor, Self tarafından verilen örneğe geri dönmeden hemen önce ayrılır.

Bayrak parametresi, diğer tüm parametrelerinden önce bildirilmiş gibi davranır. Kayıt sözleşmesinin altında, DL kaydına geçirilir. Pascal sözleşmesi kapsamında, diğer tüm parametrelerinden önce itilir. Cdecl, stdcall ve safecall kurallarının altında, Self parametresinden hemen önce itilen .

DL kayıt yapıcı veya yıkıcı çağrı yığını dıştaki olup olmadığını belirtir yana

, sen BeforeDestruction veya AfterConstruction düzgün denilen olabilir böylece çıkmadan önce DL değerini geri yüklemelisiniz.

Yani diğer geçersiz kodlama, eax beri nesne nil yüzden doğrudan yıkıcı çağırabilir değil, olabilir: asm tüm durumda
procedure Doit(ClassType: pointer); 
asm // eax=TList 
    mov dl,true 
    call TObject.Create 
    push eax 
    call TList.Pack 
    pop eax 
    mov dl,true 
    call TList.Destroy 
end; 

, nesne erişimi anlamına gelmez bu şekilde yapılmalı. Tip bilgisine doğrudan erişiminiz yoktur, bu yüzden onunla çalışmak çok zor olabilir. Mevcut bir class örneğiyle, asm yöntemleriyle istediğinizi yapabilirsiniz; ancak örnekler oluşturmak ve sınıf türleri ile oynamak için, asm kesinlikle doğal yol değil!

+0

+1 yakalama için teşekkür ederiz, yan not: Özel olarak sizinle irtibata geçmek istedim (projelerinizle ilgili olarak), bana e-postanızı nereden alabileceğime veya doğrudan verebildiğime dair bir link verebilir misiniz? – ComputerSaysNo

+0

@DorinDuminica Eğer sinopse projeleri ile ilgili ise, ana giriş noktası http://synopse.info adresindeki forumdur fakat aynı zamanda doğrudan webcontact01'e yazabilirsin sinopse dot info :) –

+0

Teşekkür ederim, size mail gönderdim – ComputerSaysNo