2010-08-21 4 views
1

Je reçois une valeur de retour différente chaque fois, donc je fais quelque chose de mal. Si je remplace le ajouter avec une base inc, il renvoie correctement.La fonction d'assemblage en ligne C++ ne fonctionne pas correctement

Voici le code.

#define WIN32_LEAN_AND_MEAN 

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

using namespace std; 

int Add (int _Number1, int _Number2); 

int main (int _ArgumentCount, char * _Arguments[]) 
{ 
    int nInput, nOutput; 

    nOutput = Add (1, 1); 

    cout << "1 + 1 = " << nOutput << endl; 
    cin >> nInput; 

    return 0; 
} 

__declspec (naked) int Add (int _Number1, int _Number2) 
{ 
    __asm xor eax, eax 
    __asm mov eax, _Number1 
    __asm add eax, _Number2 
    __asm ret 
} 

Voici le nouveau code de travail:

#define WIN32_LEAN_AND_MEAN 

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

using namespace std; 

int Add (int Number1, int Number2); 

int main (int ArgumentCount, char * Arguments[]) 
{ 
    int nInput, nOutput; 

    nOutput = Add (1, 1); 

    cout << "1 + 1 = " << nOutput << endl; 
    cin >> nInput; 

    return 0; 
} 

int Add (int Number1, int Number2) 
{ 
    __asm mov eax, Number1 
    __asm add eax, Number2 
} 
+1

Comment savez-vous que '_Number1' n'est pas' eax'? Le compilateur est autorisé à appeler des fonctions avec leurs arguments dans des registres. Je pense que votre problème est que vous n'avez fait aucun effort pour éviter de marcher sur les orteils du compilateur en déclarant vos registres utilisés, etc. Jetez un coup d'oeil à votre démontage de programme pour preuve. – Borealid

+0

Pourquoi utilisez-vous '__declspec (nu)'? Êtes-vous sûr de devoir faire cela? Que se passe-t-il si vous ne le faites pas? –

+0

@Borealid - Ceci est ma première tentative, pas vraiment sûr de ce que je fais. Je pensais que EAX était réservé pour les valeurs de retour, quels registres dois-je utiliser? @Greg - Avait quelques problèmes de compilation sans elle. Google recherché, et un gars sur un forum a dit d'utiliser la déclaration nue. –

Répondre

4

__declspec (naked) signifie que la fonction est créée sans aucun code de Prolog ou Epilogue - donc si vous voulez accéder aux paramètres formels, vous devez écrivez le code prologue de votre choix pour vous donner accès à eux. Votre xor est également accomplir rien, puisque vous remplissez immédiatement eax avec une autre valeur. Notez également que tout identifiant commençant par un trait de soulignement suivi d'une lettre majuscule est réservé, donc votre code a un comportement indéfini. Essayer de réécrire votre fonction:

int Add (int number1, int number2) 
{ 
    __asm mov eax, number1 
    __asm add eax, number2 
} 

ou écrivez bien le code pour accéder aux paramètres de la pile sans dépendre d'un Prolog:

__declspec (naked) int Add2(int number1, int number2) { 
    _asm mov eax, [esp+4] 
    _asm add eax, [esp+8] 
    _asm ret 
} 

Je ne pas vérifier, mais je suppose que votre Le code original essayait de charger les paramètres de [ebp + 8] et [ebp + 12]. Cela dépend du code Prolog normal:

push ebp 
mov ebp, esp 

... qui vous __declspec (naked) spécifiquement dit le compilateur pas à générer.

+0

+1 Bien! <......> – dirkgently

+0

Merci beaucoup. J'avoue, quand il n'a pas compilé, et j'ai trouvé la "solution" nue, je n'ai même pas lu dedans. Très paresseux de moi. Je n'avais aucune idée des noms réservés. Merci beaucoup, je travaille maintenant. –

Questions connexes