I am not a professional at assembly by any means and am receiving the following error when running my code: "Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call."
I am currently working on binding C-style functions to Python 3.2 using the CPython library and have run into an issue in my code with passing doubles. I have a single template function that is used to call the C func开发者_如何学JAVAtion that is prototyped as such:
template <const char* MODULE, const char* FUNCTION>
static PyObject* ModuleFunction (PyObject* self, PyObject* param);
Currently my method works for passing integral types between Python and C/C++, but I'm having trouble with doubles. Maybe someone more well versed in x86 assembly can spot what I'm doing wrong. I've extracted all the code that does not involve doubles in my snippet:
__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 on the following functions I used that may not be clear to everyone:
PyObject* Py_GrabElementFromTuple(PyObject* tuple, int index);
PyObject* Py_WrapDouble(double d);
double Py_ExtractDouble(PyObject* obj);
The above functions are all wrappers I wrote around CPython methods to add error checking.
Your pushes and pops are only symmetrical if the exractDouble
path is taken. In case you jump to endLoop
you have two more pushes than pops. Generally you should avoid branches between function argument pushing and the actual function call, unless you know what you are doing.
Additionally the fstp qword ptr [esp]
seems wrong, because it overwrites the return address. You probably want to subtract 8 from esp before and of course adjust the stack after the call again.
精彩评论