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]  \ 
    } \ 
} 

En utilisant la macro ci-dessus provoque le compilateur pour lancer cette erreur:macro préprocesseur code basé donne une erreur C2400

error C2400: inline assembler syntax error in 'second operand'; found 'RESTORE'

Qu'ai-je fait mal?

EDIT:

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]   \ 
} 

Le code ci-dessus ne fonctionne pas non plus:

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

+0

Est-ce que quelque chose se démarque lorsque vous regardez les résultats du préprocesseur? – torak

+0

Eh bien, il ne semble pas y avoir de sauts de ligne dans le résultat. – shadeMe

Répondre

0

L'a corrigé en incluant le corps de la fonction dans une autre étendue.

0

Au moins la dernière fois que je l'ai essayé, vous ne pouviez pas créer des étiquettes à l'intérieur d'un bloc de montage en ligne dans VC++. L'utilisation d'étiquettes de type C fonctionne bien:

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]  \ 
    } \ 
} 

Je n'ai pas écrit tout ensemble en ligne dans VC++ pour un certain temps, donc je ne peux pas garantir que cela fonctionnera, mais je suppose qu'il ya une chance assez juste .

+0

Juste testé avec VS2010 et j'ai été capable de créer des étiquettes sans aucun problème et semble me rappeler que c'était possible depuis un certain temps. – torak

+0

Je vois. Je vais essayer ça. EDIT: Hmm, pas bon. L'appel jz soulève toujours l'erreur, parmi les autres nouvelles erreurs. Juste pour clarifier, j'utilise VS 2008. – shadeMe

0

J'ai été sans accès à l'ordinateur, donc j'espère que vous avez déjà résolu cela. Je pense que le problème est que l'utilisation de "\" pour terminer la ligne indique au préprocesseur C de fusionner la ligne suivante avec cette ligne. Voir le commentaire 3 sur this page, et l'épissage de ligne here. Cela fonctionne bien pour la plupart des instructions C, mais est plus problématique pour l'assemblage, car les nouvelles lignes sont la manière dont il déline les instructions.

Je peux penser à deux approches d'une solution. Le premier est de trouver quelque chose comme C ";" qui peut être utilisé comme un séparateur de statment dans l'assemblage, je ne sais pas si une telle chose existe. La deuxième approche consiste à tout emballer dans des instructions distinctes __asm. Prendre la deuxième approche que vous obtenez, ce qui suit:

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]}  \ 
} 

NOTE: Je l'ai laissé les étiquettes en dehors des déclarations asm parce que:

  1. Je pense que vous pouvez
  2. Je ne suis pas sûr les règles de cadrage pour les étiquettes définies dans __asm blocs
+0

L'opérateur jeton-paste dans la 3ème ligne n'est pas reconnu comme un - Le compilateur pense qu'il s'agit d'une directive. Question éditée avec le code modifié. – shadeMe

+0

@shadeMe: Vous pouvez essayer de retirer la pâte symbolique de l'assemblage et d'utiliser le pointeur de fonction à la place. – torak

0

Juste une supposition sauvage: la macro développer tout le texte à une seule ligne, de se retrouver avec add esp, [k...] jz RESTORE jmp k.... Peut-être qu'il est utile de mettre un point-virgule à la fin de chaque instruction de l'assembleur.

Une indication pour cette hypothèse est que l'erreur se produit sur votre deuxième "ligne". Le premier est correct, mais le second sera fusionné au premier, c'est donc la première occasion pour le compilateur d'être confus. Si l'erreur avait été quelque part plus tard, ce ne serait probablement pas le cas.

Questions connexes