2010-02-22 2 views
8

그래서 C++ DLL에서 함수를 호출하고 싶습니다. 몇 가지 이유 때문에 저는 C++ 코드의 __asm ​​블록에서 호출하고 싶습니다. 내 질문은 이것이다 : 나는 함수를 호출하기 전에, 나는 함수의 호출 convention.However에 의해 지정된 순서대로 스택에 인수를 추진한다는 것을 알고, 내가 단순히 같은 것을 수행 할 수 있습니다인라인 어셈블리에서 인수를 호출 할 때 C++ 함수에 인수를 전달하는 방법

int a=5; 
double b = 5.0; 
__asm{ 
     push b 
     push a 
     call functionAddress 
} 

나는 어셈블리의 표준 워드 크기가 2 바이트 인 반면 C++의 int 크기는 대개 4 바이트이고 double은 8 바이트라는 사실을 염려하고 있습니다. 위의 예제에서 나는 실제로 각 변수의 전체 값 또는 바이트의 처음 몇 개를 밀고 있습니까? 위의 코드가 정확하지 않은 경우 올바른 방법은 무엇입니까? 또한 호출하는 함수가 double을 반환하면이 값은 어디에 저장됩니까? 그것은 단지 32 비트 (4bytes)를 저장할 수 있기 때문에 나는 그것이 레지스터에있을 수 없다고 가정합니다.이 엉망으로 어떤 도움이 크게 감사하겠습니다 :)

+2

시도 할 때 어떤 일이 발생 했습니까? – Seth

+0

double에 문제가 있습니다. double 인수를 취하여 입력이 5.0보다 큰 경우 dll에서 테스트 함수를 작성했습니다. 어셈블리에서 함수를 몇 번 호출하려고했습니다. 인수가 7.45454이고 반환 값이 항상 같지는 않습니다. –

답변

13

당신은 정기적으로 PUSH 명령을 사용할 수 없습니다, 같은 복식으로 8 바이트 값을 밀어합니다. 부동 소수점 매개 변수 (또는 복식)를 부동 소수점 스택으로 푸시하지 마십시오. 이 지방 매개 변수를 '손으로'스택에 넣어야합니다. 예를 들어 π을 매개 변수로 함수 f에 푸시하려면 :

__asm { 
    FLDPI     // load pi onto FP stack 
    SUB ESP,8    // make room for double on processor stack 
    FSTP QWORD PTR [ESP]  // store pi in proc stack slot (and pop from FP stack) 
    CALL f 
    ADD ESP,8    // clean up stack (assuming f is _cdecl) 
    } 
1

일반적으로, 당신은 컴퓨터의 전체 크기 워드. 이것은 칩에 따라 다르지만 32 비트 인텔은 4 바이트이고 64 비트 인텔은 8입니다 (컴파일러에 따라 - Visual Studio는 여전히 IA32 어셈블리 만 지원하므로 4 바이트).

가장 좋은 대답은 특정 컴파일러의 설명서를 보는 것입니다.

4

32 비트 x86 아키텍처는 스택에 푸시 된 값을 32 비트로 자동 채 웁니다.

명심해야 할 것이 있습니다. 호출하는 함수가 __cdecl 호출 규칙을 사용하는 경우 나중에 밀어 넣은 내용을 "팝업"해야합니다. 그러나 __stdcall 함수의 경우이 작업을 수행하면 안됩니다.

extern "C" int __cdecl function1(int, double); 
extern "C" double __stdcall function2(char, char*); 

int a = 5; 
double b = 5.0; 
int retval1; 
char c = '5'; 
char *d = "Hello"; 
double retval2; 

__asm { 
    push b 
    push a 
    call function1 
    add esp, 4*2 // "pop" what we pushed 
    mov retval1, eax 
    push d 
    push c 
    call function2 
    mov retval2, eax 
} 
+2

C++에서 동등한 호출을하고, 최적화를 비활성화하고 컴파일 한 다음 어셈블리 출력을 살펴보면 안심할 수 있습니다. 그것은 당신이하는 일과 대략 일치해야합니다. –

+1

그런데, 어떻게 두 번 밀어 주겠습니까? C에서 + + 8 바이트, 맞죠? –