2013-12-12 2 views
1

개체를 반환하는 C++로 작성된 메서드가 있습니다. 이 메소드는 어셈블리를 통해 호출됩니다 (매우 긴 이유가 있음). 예 :C++에서 개체 데이터 반환 어셈블리에서 호출 된 메서드

Person DoStuff(int a) 
{ 
    Person output; 

    output.Name = "Koder"; 
    output.Age = 1337; 
    output.Cash = 80.86; 

    cout << "Given number is " << a << endl; 

    return output; 
} 

가치에 의한 반품은 불쾌하고 좋지 만,이 문제는 관련이 없습니다. 이 메서드를 호출하면 다음과 같이 표시됩니다.

Variant vMethod = &DoStuff; 
void* pMethod = vMethod.As<void*>(); 

int paramVal = 78; 

int* retVal = nullptr; 

__asm 
{ 
    push paramVal 
    call pMethod 
    mov retVal, EAX 
} 

이 메서드의 반환 값이 int 일 때이 메서드는 완벽하게 작동합니다. 그러나 이제 객체를 반환하면 실제 call 명령어는 예외를 발생시킵니다. 추측 할 수 있듯이 예외는 return 성명서에 있습니다. 나는 이것이 이런 방식으로 썼을 때 일어날 것이라는 것을 알았지 만, 원시가 아닌 (또는 정수가 아닌) 반환 값을 검색하는 방법에 대한 단서가 없습니다. 인터넷 검색/어셈블리 함수 호출은 전체적으로 도움이되지 못했습니다. 도움을 줄 수있는 사람에게 감사드립니다.

+2

나는 그것에 대한 단서가 없다. 가장 좋은 추측은 : C++을 사용하여 함수를 호출하고 실행 파일을 생성하는 대신 어셈블리 코드 (gcc -S)를 생성하고 반환 값이 처리됩니다. –

+0

코드를 분해하면 도움이되었습니다. 메서드 호출 및 반환 값 반환 스택을 초기화하는 방법을 볼 수있었습니다. 감사! –

답변

1

어떤 종류의 호출이 사용 되는가에 따라 달라집니다. Calling Convention 또한 컴파일러가 객체를 처리하는 방법에 따라 다릅니다. 이 경우 객체에는 적어도 3 개의 값이 포함되어 있으므로 모든 값이 레지스터에 들어 가지 않을 수 있습니다 (코드는 EAX에 반환 값이 있다고 가정합니다 - int를 반환하는 경우 코드가됩니다).

어셈블리를 보면 x86 32 비트 어셈블리를 사용하고있는 것처럼 보입니다. 이 경우 호출 규칙에 스택에 인수를 전달해야한다고 나와 있습니다. 이 경우 저는 x86 비트에 대한 호출 규칙에서 반환 값에 대한 메모리를 직접 예약하고 객체를 저장해야하는 주소를 전달해야한다고 말합니다 매개 변수로. Windows에서 반환 포인터 (객체를 저장할 주소)는 두 번째 매개 변수이며 Linux에서는 첫 번째 매개 변수입니다.

DoStuff 메서드는 반환 주소를 덮어 쓰며 반환 명령에서 프로그램이 충돌하게 만들었으므로 실패했습니다.

+0

이 내용과 제공된 설명을 통해 알아낼 수있었습니다. 출력을 위해 스택에 공간을 예약하고 WORD의 오브젝트를 역순으로 (오른쪽에서 왼쪽으로) 스택으로 밀어 넣어야했습니다. –

관련 문제