Question

Je ne suis en aucun cas un professionnel de l'assemblage et je reçois l'erreur suivante lors de l'exécution de mon code :"Échec du contrôle d'exécution n°0 - La valeur de l'ESP n'a pas été correctement enregistrée lors d'un appel de fonction."

Je travaille actuellement sur la liaison des fonctions de style C à Python 3.2 à l'aide de la bibliothèque CPython et j'ai rencontré un problème dans mon code avec le passage de doubles.J'ai une seule fonction de modèle utilisée pour appeler la fonction C qui est prototypée comme telle :

template <const char* MODULE, const char* FUNCTION>
static PyObject* ModuleFunction (PyObject* self, PyObject* param);

Actuellement, ma méthode fonctionne pour transmettre des types intégraux entre Python et C/C++, mais j'ai des problèmes avec les doubles.Peut-être que quelqu'un de plus familiarisé avec l'assemblage x86 pourra repérer ce que je fais de mal.J'ai extrait tout le code qui n'implique pas de doubles dans mon extrait :

__asm
{
      mov ecx, num_params
      mov ebx, 0
      cmp ebx, ecx
      je functionCall

    extractParameters:
      mov ebx, ecx
      dec ebx
      push ecx // save ecx
      push ebx
      push param
      call Py_GrabElementFromTuple
      pop edx // I know I could modify esp, but this made it more readable to me
      pop edx
      push eax // push the returned PyObject* onto the stack

      mov edx, 0
      mov ecx, dword ptr [paramTypes]
      mov dl, byte ptr [ecx+ebx]
      cmp decimal, edx
      je extractDouble
      jmp endLoop

    extractDouble:
      call Py_ExtractDouble
      pop ebx
      pop ecx
      fstp qword ptr [esp]
      jmp endLoop
    endLoop:
      loop extractParameters

    functionCall:
      call func

      mov ecx, dword ptr [stacksize]
      add esp, ecx

      mov edx, returnType
      cmp decimal, edx
      je wrapDouble
      jmp done

    wrapDouble:
      fstp qword ptr [esp]
      call Py_WrapDouble
      mov returnObj, eax
      jmp done

    done:
}

Clarification sur les fonctions suivantes que j'ai utilisées et qui peuvent ne pas être claires pour tout le monde :

PyObject* Py_GrabElementFromTuple(PyObject* tuple, int index);
PyObject* Py_WrapDouble(double d);
double Py_ExtractDouble(PyObject* obj);

Les fonctions ci-dessus sont toutes des wrappers que j'ai écrits autour des méthodes CPython pour ajouter une vérification des erreurs.

Était-ce utile?

La solution

Vos poussées et pops ne sont symétriques que si le exractDouble le chemin est emprunté.Au cas où vous sauteriez vers endLoop vous avez deux poussées de plus que des pops.En règle générale, vous devez éviter les branches entre la poussée des arguments de fonction et l'appel de fonction réel, à moins que vous ne sachiez ce que vous faites.

De plus le fstp qword ptr [esp] semble faux, car il écrase l'adresse de retour.Vous souhaitez probablement soustraire 8 de esp avant et bien sûr ajuster à nouveau la pile après l'appel.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top