2012-05-16 4 views
5

내가하고 싶은 것은 어셈블리를 사용하여 클래스 인스턴스를 만들고 그 중 하나를 호출 한 다음 인스턴스를 해제하는 것입니다.델파이 인라인 어셈블러를 사용하여 클래스 인스턴스 만들기

나는 매우 중요한 무엇인가를 놓치고 있고 아마도 매우 간단하다는 것을 알고있다. 그러나 나는 무엇을 모른다.

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. 

FYI : 나는 이것을 낮은 수준에서 어떻게 달성 할 수 있는지, 다른 방법으로는 이해할 수 없다는 것을 알고 싶습니다.

UPDATE : 오히려 PUSH보다, EBX를 사용하여 결함을 찾기위한 아르노에

감사 :

갱신 2 : 안드레아스 Rejbrand에

덕분에, 나는 범인을 찾기 위해 관리했습니다/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는 저장해야합니다 - Arnaud의 대답을보세요 – PhiS

+0

@PhiS 예 선생님, Arnaud의 답변을 읽었습니다. 누구에게나 관심이있는 사용자는 모든 답변 (2 개만 읽음)과 댓글 (: – ComputerSaysNo

+0

)을 읽습니다. 당신이 EBX를 저장하지 않고 사용하고있는 질문에 대한 당신의 업데이트에서 이런 함수를 사용하는 실제 프로그램이 충돌을 일으킬 위험이 있기 때문에이를 수정하십시오 (eg ebx/pop ebx를 푸시하십시오) 그 이유는 찾기가 매우 어려울 것입니다 ... – PhiS

답변

2

델파이 어셈블리 프로그래밍 우수 가이드, 원래 발견 here. 안타깝게도 사이트는 다운되었지만 보관 된 버전 here을 찾을 수 있습니다. 특히 page 5을 찾으십시오.

+0

+1). 고맙습니다! – ComputerSaysNo

+0

이론적으로는 질문에 대답 할 수 있지만, 귀하의 답변에 링크 된 기사의 필수 부분을 제공하고 [참고 용 링크] (http://meta.stackexchange.com/q/8259)를 제공하십시오. 링크 썩음으로 인한 위험. – Kev

+3

@Kev : 저는 그것을 완벽하게 알고 있습니다. 그래서 그것이 그렇게하도록 요청받은 후에 만이 답을 보낸 이유입니다. 원래는 링크를 주석으로 만 제공했으나 주석을 삭제 한 이후 더 이상 명확하지 않습니다. 불행히도, 나는 지금 내가 링크 된 페이지의 주제를 배우는 데 시간/에너지가 없다. –

10

비밀번호가 올바르지 않습니다.

ebx 레지스터가 오버로드되어 있습니다.이 레지스터는 보존해야합니다. 그리고 글로벌 변수 트릭은 의미가 없습니다.

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); 

을하지만 그것은 try...finally와 인스턴스를 보호하지 않습니다

더 나은 코딩해야한다. :)이 mov dl,true 매개 변수에 대한

, this official page from the EMB wiki을 참조하십시오

생성자와 소멸자가 추가 부울 플래그 매개 변수가 에 전달되는 것을 제외하고, 다른 방법과 동일한 호출 규칙을 사용하여 생성자의 컨텍스트를 표시 또는 소멸자 호출.

생성자 호출의 플래그 파라미터 거짓 값은 생성자 인스턴스 오브젝트를 통해 호출 또는 상속 키워드를 사용하는 것을 나타낸다. 이 경우 생성자는 일반 메소드처럼 작동합니다. 생성자 호출의 플래그 매개 변수에서 True 값은 생성자가 클래스 참조를 통해 호출되었음을 나타냅니다. 이 경우 생성자는 Self에서 제공된 클래스 의 인스턴스를 만들고 EAX에서 새로 만든 객체에 대한 참조를 반환합니다.

소멸자 호출의 플래그 매개 변수에서 False 값은 상속 된 키워드를 사용하여 소멸자가 호출 된 을 나타냅니다. 이 의 경우, 소멸자는 일반적인 메소드처럼 동작합니다. 소멸자 호출의 플래그 매개 변수에 True 값이 있으면 소멸자가 인스턴스 개체를 통해 호출되었음을 나타냅니다.이 경우 소멸자는 반환 직전에 Self가 제공 한 인스턴스의 할당을 해제합니다.

플래그 매개 변수는 다른 모든 매개 변수 앞에 선언 된 것처럼 작동합니다. 등록 규칙에 따라 DL 레지스터에 전달됩니다. 파스칼 규칙에 따라 다른 모든 매개 변수보다 먼저 푸시됩니다. cdecl, stdcall 및 safecall 규칙에 따라 Self 매개 변수 바로 전에 을 푸시합니다.

DL 레지스터는 생성 자나 소멸자 가 호출 스택의 가장 바깥쪽에 있는지 여부를 나타내는 때문에

, 당신은 BeforeDestruction 또는 AfterConstruction을가 가 제대로 호출 할 수 있도록 종료하기 전에 DL 의 가치를 복원해야합니다.

그래서 다른 유효한 코딩, eax 이후 우리의 목적은 nil 그래서 우리는 직접 소멸자를 호출 할 수없는,있을 수 : asm 모든 경우
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; 

, 개체 액세스가 의미하지 않는다 이렇게 할 수 있습니다. 형식 정보에 직접 액세스 할 수 없기 때문에 형식 정보를 사용하기가 매우 어려울 수 있습니다. 기존 class 인스턴스를 사용하면 asm 메소드로 원하는대로 할 수 있습니다. 그러나 인스턴스를 만들고 클래스 유형으로 재생하려면 asm은 확실히 자연스러운 방법이 아닙니다!

+0

+1 캐치 사이드 노트에 감사드립니다. 개인적으로 (귀하의 프로젝트 중 일부와 관련하여) 개인적으로 연락하고 싶었습니다. 전자 메일을받을 수있는 곳이나 직접 제공 할 수있는 링크를 제공 할 수 있습니까? – ComputerSaysNo

+0

@DorinDuminica 그것은 synopse 프로젝트에 관한 경우, 주요 진입 점은 http://synopse.info에서 포럼이지만 직접 내 webcontact01에서 synopse 도트 정보 :) 쓸 수 있습니다 –

+0

메일을 보내 주셔서 감사합니다 – ComputerSaysNo

관련 문제