2010-02-18 7 views
3

기본적으로, 나는 이런 식으로 뭔가를 할 수 있도록하고 싶습니다 :인라인 어셈블리의 "call"명령에 문자열을 인수로 전달하는 방법은 무엇입니까?

//assume myFunction is defined and takes one argument that is an int 
char * functionName = "myFunction"; 
int arg = 5; 

__asm{ 
    push a 
    call functionName 
} 

은 기본적으로 내가 그의 이름 문자열에 저장되어있는 함수를 호출합니다. 이것을하기위한 적절한 구문은 무엇입니까?

편집 : 우리는 적어도 직접적으로, 86 어셈블리

+0

질문을 수정하십시오. char * _ 인수로 _single int가 무엇을 의미합니까? 중요한 세부 사항을 놓치셨습니까? 어떤 종류의 프로세서를보고 계십니까? 일반적인 아이디어 나 실제 x86과 같은 어셈블리 코드를 원하십니까? – dirkgently

+0

샘플을 이해할 수 없습니다. 호출은 문자열이 될 수 없으며 함수 포인터에 연결되어야합니다. 함수를 호출하려면 함수에 대한 포인터를 가져와야합니다. 한 가지 가능성은 자신의 DLL에서 GetProcAddr을 사용하는 것입니다. –

+0

혼란에 빠져서 죄송합니다. 함수가 int 형의 인수 하나를 취한다는 것을 의미합니다. 호출되는 함수는 중요하지 않습니다. 왜 스택에 "a :"를 넣을지를 설명하는 것입니다. –

답변

1

당신은 할 수없는 얘기.

호출은 주소를 매개 변수로 취합니다. "call functionName"을 쓰더라도 링커는 functionname을 함수의 실제 주소로 바꿉니다. 먼저 해당 문자열을 해당 주소로 매핑해야합니다. 일반적으로 C와 C++은이를 허용하는 함수 이름 매핑에 대한 런타임 메타 데이터를 지원하지 않습니다. DLL에서 함수를 내 보낸 경우 GetProcAddress를 사용하여 해당 주소를 찾을 수 있습니다.

함수 목록이 정적 인 경우 미리 자신을 매핑 할 수 있습니다. 같은

뭔가 :

std:map<string, PVOID> functionMappings; 
functionMappings["MyFunction"] = MyFunction; 


// Later 


PVOID function = functionMappings["MyFunction"]; 

__asm 
{ 
    push a; 
    call [function] 
} 

일부 노트 :

나는 표준이 함수 포인터가 PVOID보다 클 수 있다고 생각합니다. 이것은 Windows x86/x64 플랫폼에서 작동합니다.

사용중인 호출 규칙을 말하지 않았습니다.이 코드는 stdcall을 가정합니다.

이것은 매우 성취하기를 원하는 것입니다. 어떤 문제를 해결하려고합니까?

+0

사용할 필요가 있다고 생각합니다. .이 바보 같은 질문이지만, 무엇 exaclty 그 함수의 형 반환 값의 경우 GetProcAddress를 다음 죄송합니다 예를 들어, 것 'INT의 A = GetProcAddress를 (dllHandle, "myFunction이");??' 작업 –

+0

Btw, 코드에서 __stdcall을 제안하는 것은 무엇입니까? 호출자가 스택에서 인수를 팝하지 않고 있거나 다른 것이 있습니까? –

+0

__stdcall은 호출 규칙입니다. 함수 호출을 수행하는 어셈블리를 작성하는 경우에는 호출 규칙을 이해해야합니다. 리소스는 GetProcAddress 및 호출 규칙에 대해 네트워크에서 사용할 수 있습니다. MSDN에는 심지어 GetProcAddress에 대한 반환 값을 사용하는 방법을 보여주는 샘플 코드가 있습니다. – Michael

0

짧은 답변 : 허용되는 경우이를 잊어 버리면 구현하기가 너무 어려울 것입니다.

길게 대답 : 내가 생각할 수있는 가장 쉬운 방법은 문자열을 함수 (또는 더 정확하게 함수 포인터)에 매핑하는 조회 테이블을 만드는 것입니다. 먼저 해당 맵을 보유하기위한 합리적인 데이터 구조를 생각하고 조회 중에 키와 functionName을 비교하기 위해 문자열 비교 함수를 구현해야합니다. 마지막으로, 매핑 항목을 해당 테이블 구조에 수동으로로드해야합니다.

(나는 더 이상 구체적인 사항을 언급하지 않을 것입니다. 왜냐하면 내 어셈블러 날짜가 먼 과거와 두 번째 때문입니다. 원하는 것을 달성 할 수 없다면 조금 궁금 해서요. 다른 구현하기 쉬운 솔루션 ... 죄송합니다.)

1

이 작업은 불가능합니다. 이름으로 전화를 걸려고합니다. Assembler는 값에 의한 call-by-value만을 가지고 있는데, value는 주소입니다. 이름을 주소로 변환하고 주소를 어셈블러에 전달해야합니다. 즉, 이름과 주소 사이에 일종의 상호 참조가 필요합니다. 컴파일러가 여기에서 도움을 줄 수 있습니다. C 및 C++에서는 어셈블러에 전달할 수있는 함수의 주소를 가져 오는 데 필요한 구문을 보려면 함수 포인터를 찾아야합니다.

선제 : 예, 때로는 컴파일러가 심볼을 실행 파일에 포함 할 수 있는데,이 심볼은 검색 할 수 있지만 문제가 많습니다.데이터의 형식은 컴파일러 버전간에 변경 될 수 있으며 정보는 링커에 의해 제거 될 수 있습니다.

0

나는 이것을 쉽게 할 수있는 방법을 모른다. 일부 상위 언어에서는 리플렉션을 사용하여이를 수행 할 수 있지만 C 나 어셈블리 모두 해당 기능을 사용할 수 없습니다. 링커가 끝날 때까지 모든 함수 호출은 주소로 해석됩니다. 어쩌면 일부 디버그 인프라에 액세스 할 수있는 경우 함수 이름에 역방향 조회를 수행하여 해당 주소를 가져올 수 있지만 어셈블리를 통해 얻는 것은 쉬운 일은 아닙니다.

또는 컴파일 할 때 정의한 함수 포인터를 사용하여 관심있는 함수의 주소를 저장할 수 있습니다 (문자열을 함수 포인터로 변환하는 방법이 필요 하겠지만, 아마도 문자열 비교 테이블 조회를 통해 가능할 수 있습니다). 이게 당신이 흥미있는 일이라면 C 코드를 작성하고 컴파일러가 함수 포인터를 처리하는 방법을 보도록 출력하는 어셈블리 코드를 살펴볼 것을 제안합니다.

관련 문제