2017-02-01 1 views
0

내 자신의 JIT를 만들려고 노력 중이며 아주 간단한 어셈블리 코드 (machine-code)를 실행할 수 있지만이 방법으로 함수를 호출하는 방법을 찾는 데 어려움이 있습니다. Visual Studio에서 디스 어셈블리 창에서 함수를 볼 수 있습니다.x86_64 어셈블리에서 함수 호출

또 다른 관련 질문은 기계어로 Win32 MessageBox()를 호출하는 방법입니다.

다음 질문은 어떻게 이런 방식으로 외부 DLL/LIB 함수를 호출합니까?

또한이 주제에서 저를 더 가르쳐 줄 수있는 책이나 자습서가 있습니까? 나는 그것을 찾으려고 노력했지만 .NET, JVM 및 LLVM과 같은 결과를 얻고 싶습니다. 내가 생각한 바가 아닙니다. 여기

내가 코드의 단순화 된 버전 일하고된다 :

#include <iostream> 
#include <Windows.h> 

int main(int argc, char* argv[]) 
{ 
    // b8 03 00 00 00 83 c0 02 c3 
    unsigned char code[] = { 
     0xb8,     // mov eax, 3 
     0x03, 0x00, 0x00, 0x00, // 3 (32 bit) 
     0x83,     // add eax, 2 // 0x83 = add, 
     0xc0,     // ModR/M with immediate 8 bit value 
     0x02,     // 2 (8 bit) 
     0xc3     // ret 
    }; 

    void* mem = VirtualAlloc(0, sizeof(code), MEM_COMMIT, PAGE_EXECUTE_READWRITE); 

    memcpy(mem, code, sizeof(code)); 

    DWORD old; 
    VirtualProtect(mem, sizeof(mem), PAGE_EXECUTE_READ, &old); 

    int(*func)() = reinterpret_cast<int(*)()>(mem); 

    printf("Number is %d\n", func()); 

    VirtualFree(mem, 0, MEM_RELEASE); 

    return 0; 
} 

IT는 C++ 함수를 호출 할 수있는 JIT 어셈블리 코드를 가질 수 있습니까?

이 프로젝트를 시작하기 전에 C++로 바이트 코드 인터프리터를 만들었지 만 C#의 동등한 테스트 프로그램과 비교할 때 속도에 만족하지 않았습니다. C#은 약 25 배 빠릅니다. 그래서 JIT라는 것을 빨리 발견하기 위해 비틀 거리게되었습니다. 그래서 저는 여러분 모두가이 JIT 프로젝트를 어디서 볼 수 있는지 알기를 바랍니다. 가능하다면 GUI를 처리하도록하십시오.

+0

물론 가능합니다. 주위에 Gazillion 예를 들어, 어쩌면 [안녕하세요 세상] (http://stackoverflow.com/a/1032422/547981) 우선 봐. 손으로 그것을 조립 재미 있지만되지 않습니다. 함수 호출이 병목 현상을 일으키지는 않습니다. – Jester

+1

나는 일반적으로 C/C++로 샘플 프로그램을 작성한 다음 어셈블리 레벨 이름과 호출 순서를 얻기 위해 컴파일러 출력 어셈블리 코드를 가지고있다. Visual Studio 2015의 경우 printf는 이제 include 파일의 일부로, C/C++ 코드로 인라인됩니다. 이 문제를 해결하는 한 가지 방법은 printf 용 C 파일과 나머지 프로젝트 용 어셈블리 파일을 포함하는 프로젝트를 만드는 것입니다. 이전 스타일의 printf를 포함하는 특정 라이브러리를 가져 오는 옵션이있을 수 있습니다. – rcgldr

+0

음, IIRC, C 소스를 메모리에 컴파일하기 위해 clang을 구부린 다음 LLVM으로 기계 코드로 JIT하여 실행하면 LLVM 소스를 연구하면 몇 년 내에 대답을 얻을 수 있습니다. 왜 내가 해석 된 언어 속도에 귀찮아하고 단순히 C++ 및 어셈블리로 성능 파트를 작성해야하는지에 대해 잘 모르는 경우 JIT는 일반적으로 최선의 경우에는 거의 작동하지 않으며 제대로 조정 된 성능 사례에서는 성능이 저조합니다. 성능이 중요하지 않은 부품의 경우 25x도 중요하지 않습니다. C++이 얼마나 멋진 지 알아내는 것이 좋은 운동 일지 모르지만. :) – Ped7g

답변

0

아마도 컴파일러/링커 작성에 대한 자습서를 찾을 수 있습니다. 동적 라이브러리를 구현/호출하는 데 도움이 될 수 있습니다.

C++ 함수를 호출하여 정확히 무엇을 의미하는지 모르겠습니다. 어쨌든 필자는 다음과 같은 데모 프로그램을 작성하여 사용자가 살펴보고 전혀 도움이되는지 확인할 수 있습니다.

#include <Windows.h> 
#include <iostream> 


using namespace std; 

__int64 sub(__int64 a, __int64 b) 
{ 
    return a - b; 
} 

int main(int argc, char **argv) 
{ 
    char code[] = 
    { 
     0x48, 0x89, 0xC8,   // mov rax, rcx 
     0xC3,      // ret 

     0x48, 0x83, 0xEC, 0x20,  // sub rsp, 0x20 
     0xFF, 0xD0,     // call rax 
     0x48, 0x83, 0xC4, 0x20,  // add rsp, 0x20 
     0xC3      // ret 
    }; 


    char *mem = static_cast<char *>(VirtualAlloc(0, sizeof(code), MEM_COMMIT, PAGE_EXECUTE_READWRITE)); 

    MoveMemory(mem, code, sizeof(code)); 

    auto setFunc = reinterpret_cast<void *(*)(void *)>(mem); 
    auto callFunc = reinterpret_cast<__int64 (*)(__int64, __int64)>(mem + 4); 

    setFunc(sub); 
    __int64 r = callFunc(0, 1); 
    cout << "r = " << r << endl; 

    VirtualFree(mem, 0, MEM_RELEASE); 


    cin.ignore(); 
    return 0; 
} 
+0

C++이'setFunc (sub);'과'__int64 r = callFunc (0, 1);'사이에'rax'를 오염시키는 것을 어떻게 막을 수 있습니까? IMO 이것은 안정적인 예가 아닙니다 (합리적으로 낮은 최적화 수준과 충분한 행운으로 작동 할 수도 있음). – Ped7g

+0

@ Ped7g 내 요점은 그 코드를 그대로 사용할 수 있다는 것이 아닙니다. 함수를 직접 호출 할 수 있다면 어쨌든 왜 이렇게할까요? 나는 당신이 함수의 주소를이 방법으로 불러올 수 있다고 말하고자한다. 그리고 나서 당신이 원하는대로 무엇이든 할 수있다. 예를 들어 점프 테이블을 설정한다. – MegaStupidMonkeys

+0

@MegaStupidMonkeys 이것은 내가 정말로 관심을 갖고 있었던 것입니다. 고마워요! –

관련 문제