2013-07-13 3 views
4

32 비트 Windows 응용 프로그램에서 stdcall 호출 또는 cdecl이 될 수있는 외부 함수를 호출하는 코드를 작성해야합니다.
발신자 인 내 코드는 앞으로 어떤 것이 될지 미리 알 수 없습니다. 지금 stdcall로 정의 된 호출 사이트에서 cdecl 함수를 호출하려고하면 checkEsp 예외 대화 상자가 표시되고 그 이유가 여기에 있습니다.
할 방법이 있습니까?cdecl 또는 stdcall 일 수있는 함수 호출

+0

외국 기능 인터페이스 (FFI) 라이브러리를 사용해보십시오. –

+0

FFI는 여전히 호출 규칙을 알아야합니다. – shoosh

+0

@HansPassant 인수 순서가 동일합니다. – shoosh

답변

3

이 방법으로 다음을 수행 할 수 있습니다 :

  mov  esi, esp 

      push arg3 
      push arg2 
      push arg1 
      call [SomeExternalProc] 

      mov  esp, esi ; now the stack is always properly cleaned 

외부 절차는 ESI를 보존해야한다. 또는 외부 프로 시저 또는 메모리 변수 (로컬 또는 전역 변수)로 보존 된 다른 레지스터를 사용할 수 있습니다.

좋습니다. CDECL 및 STDCALL의 인수 순서가 역순으로 좋습니다.

+0

고마워요! 이것은 완벽 해 – shoosh

0

cdecl과 stdcall은 정의가 호환되지 않습니다. cdecl에서는 호출자가 스택을 정리하고 stdcall에서 호출 수신자가 스택을 정리합니다. stdcall을 가정하지만 실제로 cdecl 인 경우 아무도 스택을 지우지 않습니다. 즉, ESP (스택 포인터)가 통화 후 엉망이 될 것입니다. 어쩌면 당신이 더 자세한 정보를 주면 어쩌면 해결할 수도 있지만 스택을 엉망으로 만들지 않고 호출 규칙을 모른 채 함수를 호출 할 방법은 없습니다.

참조 : http://en.wikipedia.org/wiki/X86_calling_conventions 차이점 정의.

+0

이 상황을 확인하고 ESP를 수정하는 신뢰할 수있는 방법이 있습니까? 어쨌든 checkEsp는 무엇을합니까? – shoosh

+0

ESP가 스택 포인터입니다. 스택이 현재 어디에 있는지 추적합니다. 이론적으로 ESP를 힙에있는 변수에 저장하고 호출 한 후에 ESP를 검색 할 수는 있지만 그 일은 결코 지저분 할 것입니다 ... 나는 그것을 시도한 적이 없으므로 그렇게 될지조차 확신 할 수 없습니다. ESP가 호출 전후에 ESP가 올바르게 유지되고 있는지 확인하기 위해 사용하는 메커니즘 점검이 확실하지 않습니다. 더 나은 전략은 런타임에 호출 규칙을 프로그램 방식으로 검사하는 일관된 방법을 보지 못했지만 호출 규칙을 확인하고 그에 따라 호출을 조정하는 것입니다. – Enkid

1

또한 스택 포인터를 저장 및 복원의 부작용이있는) (alloca 함수를 사용할 수 있습니다

{ 
    alloca((uintptr_t)callback & 2); 
    callback(); 
}