通过内联 x86 将双精度值传递给函数

发布于 2024-11-07 07:38:10 字数 1717 浏览 4 评论 0原文

无论如何,我都不是汇编方面的专业人士,并且在运行我的代码时收到以下错误:“运行时检查失败#0 - ESP 的值未在函数调用中正确保存。”

我目前正在使用 CPython 库将 C 风格函数绑定到 Python 3.2,并且在我的代码中遇到了传递双精度数的问题。我有一个模板函数,用于调用原型化的 C 函数,如下所示:

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

目前,我的方法适用于在 Python 和 C/C++ 之间传递整数类型,但我在使用双精度类型时遇到了问题。也许更精通 x86 汇编的人可以发现我做错了什么。我在代码片段中提取了所有不涉及双精度数的代码:

__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:
}

对我使用的以下函数的澄清,可能每个人都不清楚:

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

上述函数都是我围绕 CPython 方法编写的所有包装器,用于添加错误检查。

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 function 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

〗斷ホ乔殘χμё〖 2024-11-14 07:38:10

仅当采用 exractDouble 路径时,您的推送和弹出操作才会对称。如果您跳转到 endLoop,则推送次数会比弹出次数多两次。一般来说,您应该避免函数参数推送和实际函数调用之间的分支,除非您知道自己在做什么。

另外,fstp qword ptr [esp] 似乎是错误的,因为它覆盖了返回地址。您可能想在之前从 esp 中减去 8,当然在再次调用之后调整堆栈。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文