2014-04-26 2 views
2

취미 프로젝트로 친구와 함께 오래된 MUD 코드베이스에서 작업하고 있지만 debian (x386 이외의 다른 OS에서 컴파일 할 코드를 가져 오는 데 문제가 있습니다.). 문제는 (대부분) 수정하기에 충분히 이해할 수없는 몇 줄의 asm 행 때문입니다. VS 컴파일 할 때 I 나타나는 오류 "오류 C2059입니다 : 구문 오류 ''라인 29이이 64 OS에서 컴파일하는 방법에 대한 어떤 생각C/C++ 머드 코드에서 asm 휘발성 문제

void  Execute(int nArgs, ...) 
{ 
    if(MAX_FUNCTION_ARGS < nArgs) 
     throw "Error: CFuncPtr has too many args"; 

    int i; 
    void *fptrs[MAX_FUNCTION_ARGS], *ptrs[MAX_FUNCTION_ARGS]; 
    va_list ap; 
    va_start(ap, nArgs); 

    for(i = 0; i < nArgs; i++) 
     fptrs[i] = va_arg(ap, void *); 
    for(i = 0; i < nArgs; i++) 
    { 
     ptrs[i] = fptrs[nArgs - i - 1]; 
// ============== This is the part with the issue 
     asm volatile("" \       // This is line 29. 
       "movl %0, %%eax\n\t" \ 
       "pushl %%eax\n\t" \ 
       :      
       : "r"(ptrs[i]) 
       : "%eax"); 
// ============== 
    } 
    (*funcptr)(); 
    va_end(ap); 
} 
+0

와우, 이것은 매우 아프다. 좋은 발견! –

답변

3

이 있기 때문에, 지금까지 사소한에서인가? x86-64는 인수에 대해 레지스터 전달을 사용합니다. 기본적으로 레지스터에 인수가 전달되지 않는다고 가정하고 호출 수신 함수가 스택의 모든 인수를 사용한다고 가정하기 때문에 오히려 추한 해결책입니다. 아마도 어셈블리 버전을 피하고 두 번째 for-loop (어셈블리 코드 사용) 대신 다음과 같이 작성하십시오.

switch(nArgs) 
{ 
    case 0: 
    (*funcptr)(); 
    break; 
    case 1: 
    (*funcptr)(fptrs[0]); 
    break; 
    case 2: 
    (*funcptr)(fptrs[0], fptrs[1]); 
    break; 
    ... Repeat until MAX_FUNCTION_ARGS is covered. 
}  

MAX_FUNCTION_ARGS가 매우 큰 경우가 아니면 나쁜 코드를 생성 할 가능성은 거의 없습니다.이 경우 [처음에는 funcptr의 호출 규칙을 변경하려고합니다.]

+0

도움을 주셔서 감사합니다! MAX_FUNCTION_ARGS는 8이므로 스위치에 그리 길지는 않습니다 (하지만이 코드베이스에서는 문제가되는 코드 문제를 잘 알고 있습니다). 머드를 새로운 코드베이스로 이식하려고 시도했지만 솔직히 오래된 코드를 현대화하는 작업이 나에게 더 나은 프로그래머가되고 C++에 대해 더 많은 것을 배우는 데 도움이 될 것이라고 생각합니다. 다시 도움을 주셔서 감사합니다! – Rezalas

+1

기존 코드를 다시 작성하면 (많은 부분을 테스트하면서) 많은 사람들이 (다른 사람들의) 코드를 읽는다는 의미와 일반적인 문제를 해결하는 방법을 배우는 데 매우 좋은 방법입니다. 두 가지 모두 매우 유용한 기술입니다. 물론 당신은 당신이 한 일이 옳았다는 것을 결정하기위한 일련의 테스트가 필요합니다! –