Передача двойного к функции через встроенный x86 - PullRequest
0 голосов
/ 14 мая 2011

Я ни в коем случае не профессионал в сборке и получаю следующую ошибку при запуске моего кода: «Ошибка проверки времени выполнения # 0 - значение ESP не было должным образом сохранено при вызове функции».

В настоящее время я работаю над связыванием функций в стиле C с Python 3.2 с использованием библиотеки CPython и столкнулся с проблемой в моем коде с передачей удваивающихся значений.У меня есть одна шаблонная функция, которая используется для вызова функции 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, чтобы добавить проверку ошибок.

1 Ответ

0 голосов
/ 14 мая 2011

Ваши нажатия и выталкивания симметричны, только если выбран путь exractDouble. В случае, если вы прыгаете на endLoop, у вас есть еще два толчка, чем хлопки. Как правило, вы должны избегать ветвей между нажатием аргумента функции и фактическим вызовом функции, если вы не знаете, что делаете.

Кроме того, fstp qword ptr [esp] кажется неправильным, поскольку перезаписывает адрес возврата. Вы, вероятно, хотите вычесть 8 из esp до и, конечно, скорректировать стек после вызова снова.

...