2010-06-29 2 views
0
#define CANCEL_COMMON_DIALOG_HOOK(name) \ 
void __declspec(naked) ##name##CancelCommonDialogHook(void) \ 
{ \ 
    __asm \ 
    { \ 
     add  esp, [k##name##CancelCommonDialogStackOffset] \ 
     jz  RESTORE \ 
     jmp  [k##name##CancelCommonDialogNewFileRetnAddr] \ 
    RESTORE: \ 
     pushad \ 
     call DoSavePluginCommonDialogHook \ 
     test eax, eax \ 
     jnz  REMOVE \ 
     popad \ 
     jmp  [k##name##CancelCommonDialogRestoreRetnAddr] \ 
    REMOVE: \ 
     popad \ 
     jmp  [k##name##CancelCommonDialogRemoveRetnAddr]  \ 
    } \ 
} 

컴파일러는이 오류를 발생시킵니다 위의 매크로를 사용하여 산출?처리기 매크로 기반 코드는 C2400 오류

편집 :

void __declspec(naked) #name##CancelCommonDialogHook(void)    \ 
{                  \ 
    __asm add  esp, [k##name##CancelCommonDialogStackOffset]  \ 
    __asm jz  RESTORE            \ 
    __asm jmp  [k##name##CancelCommonDialogNewFileRetnAddr]   \ 
    RESTORE:                \ 
    __asm pushad              \ 
    __asm call DoSavePluginCommonDialogHook       \ 
    __asm test eax, eax            \ 
    __asm jnz  REMOVE            \ 
    __asm popad              \ 
    __asm jmp  [k##name##CancelCommonDialogRestoreRetnAddr]   \ 
    REMOVE:                \ 
    __asm popad              \ 
    __asm jmp  [k##name##CancelCommonDialogRemoveRetnAddr]   \ 
} 

위의 코드는 작동하지 않습니다 중 하나 : 나는 그것을 시도 마지막으로, 당신은 인라인 어셈블리 블록의 내부 레이블을 만들 수 없습니다 적어도

error C2447: '{' : missing function header (old-style formal list?) error C2014: preprocessor command must start as first nonwhite space

+0

전처리 기의 결과를 볼 때 탁월한 점이 있습니까? – torak

+0

글쎄, 결과에 줄 바꿈이없는 것 같습니다. – shadeMe

답변

0

함수 본문을 다른 범위로 묶음으로써 문제를 해결했습니다.

0

VC++. 나는 꽤 오랫동안 VC++의 모든 인라인 어셈블리를 작성하지 않은

void __declspec(naked) ##name##CancelCommonDialogHook(void) \ 
{ \ 
    __asm \ 
    { \ 
     add  esp, [k##name##CancelCommonDialogStackOffset] \ 
     jz  RESTORE \ 
     jmp  [k##name##CancelCommonDialogNewFileRetnAddr] \ 
    }   \ 
    RESTORE: \ 
    _asm {  \ 
     pushad \ 
     call DoSavePluginCommonDialogHook \ 
     test eax, eax \ 
     jnz  REMOVE \ 
     popad \ 
     jmp  [k##name##CancelCommonDialogRestoreRetnAddr] \ 
    }   \ 
    REMOVE: \ 
    __asm { \ 
     popad \ 
     jmp  [k##name##CancelCommonDialogRemoveRetnAddr]  \ 
    } \ 
} 

, 그래서 문제가 해결됩니다 보장 할 수 없습니다,하지만 난 꽤 공정한 기회가 추측에는 요 : C 스타일의 레이블을 사용하지만 작동 .

+0

VS2010으로 테스트 한 결과 문제없이 레이블을 만들 수 있었고 꽤 오랜 시간 동안 가능하다는 것을 상기 할 수있었습니다. 나는 – torak

+0

를 본다. 이것을 시도 할 것입니다. 편집 : 음, 좋지 않습니다. jz 호출은 여전히 ​​다른 새로운 오류 중에서 오류를 발생시킵니다. 명확히하기 위해, 나는 VS 2008을 사용하고 있습니다. – shadeMe

0

컴퓨터에 액세스 할 수 없으므로 이미 해결했습니다. 그 문제는 "\"를 사용하여 줄을 끝내면 실제로이 줄과 다음 줄을 병합하는 C 전처리기를 알리는 것이라고 생각합니다. 주석 3 (this page 참조) 및 라인 접합 here을 참조하십시오. 그것은 대부분의 C 문에서는 잘 작동하지만, 새로운 선은 문을 delineate하는 방법이므로 어셈블리에 더 문제가됩니다.

솔루션에 대한 두 가지 접근 방식을 생각해 볼 수 있습니다. 첫 번째는 C의 ";" 어셈블리에서 statment 구분 기호로 사용할 수 있습니다. 그런 것이 있는지 여부는 알 수 없습니다. 두 번째 방법은 모든 것을 별도의 __asm 문으로 묶는 것입니다. 당신이 얻는 두 번째 방법을 가지고 가서, 다음

void __declspec(naked) ##name##CancelCommonDialogHook(void)   
{                  
    __asm{add  esp, [k##name##CancelCommonDialogStackOffset]}  \ 
    __asm{jz  RESTORE}           \ 
    __asm{jmp  [k##name##CancelCommonDialogNewFileRetnAddr]}  \ 
    RESTORE:               \ 
    __asm{pushad}              \ 
    __asm{call DoSavePluginCommonDialogHook}      \ 
    __asm{test eax, eax}           \ 
    __asm{jnz  REMOVE}            \ 
    __asm{popad}              \ 
    __asm{jmp  [k##name##CancelCommonDialogRestoreRetnAddr]}  \ 
    REMOVE:               \ 
    __asm{popad}              \ 
    __asm{jmp  [k##name##CancelCommonDialogRemoveRetnAddr]}  \ 
} 

참고 : 당신이

  • 내가 모르겠어요 수 있다고 생각

    1. : 때문에 어셈블리 구문 외부의 라벨을 떠 났어요 __asm 블록
  • +0

    3 행의 token-paste 연산자가 하나의 행으로 인식되지 않습니다. - 컴파일러는 지시어라고 생각합니다. 수정 된 코드로 수정 된 질문입니다. – shadeMe

    +0

    @shadeMe : 토큰 붙여 넣기를 어셈블리 밖으로 가져 와서 대신 함수 포인터를 사용해 볼 수 있습니다. – torak

    0

    그냥 추측에 정의 된 레이블에 대한 범위 지정 규칙 : 매크로 add esp, [k...] jz RESTORE jmp k...로 끝나는 한 줄에 모든 텍스트를 확장됩니다. 어쩌면 각 어셈블러 명령어의 끝 부분에 세미콜론을 넣는 것이 도움이 될 수 있습니다.

    가설에 대한 표시는 두 번째 "줄"에서 오류가 발생한다는 것입니다. 첫 번째는 괜찮지 만 두 번째가 첫 번째 클래스와 병합되므로 컴파일러가 혼란에 빠질 수있는 첫 번째 기회입니다. 오류가 나중에 어딘가에 있었다면 아마도 그렇게되지는 않을 것입니다.