gpt4 book ai didi

c++ - 将内联汇编代码转换为 C++

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:11:20 24 4
gpt4 key购买 nike

我正在做一个 cpp 项目。该项目需要迁移到 64 位。它包含一些无法在 x64 上编译的内联汇编代码。这是包含汇编代码的函数:

void ExternalFunctionCall::callFunction(ArgType resultType, void* resultBuffer)
{
#if defined(_NT_) || defined(__OS2__)

// I386

// just copy the args buffer to the stack (it's already layed out correctly)
int* begin = m_argsBegin;
int* ptr = m_argsEnd;
int arr[1000], i=0;
while (ptr > begin) {
int val = *(--ptr);

__asm push val
}

void* functionAddress = m_functionAddress;

// call the function & handle the return value. use __stdcall calling convention
switch (resultType) {
case voidType:
__asm {
call functionAddress
}
break;
case pointerType:
case int32Type:
__asm {
call functionAddress
mov ebx, resultBuffer
mov dword ptr [ebx],eax
}
break;
case floatType:
__asm {
call functionAddress
mov ebx, resultBuffer
fstp dword ptr [ebx]
}
break;
case doubleType:
__asm {
call functionAddress
mov ebx, resultBuffer
fstp qword ptr [ebx]
}
break;
}

我使用堆栈、数组来迁移这个“asm push val”,但没有用。虽然,它不会抛出任何编译错误,但逻辑不起作用。

所以,我想问一下,我可以在 C++ 中使用什么来代替“__asm push val”。任何帮助将不胜感激。

最佳答案

这个问题一般来说是不可解的;那是因为评论,

// call the function & handle the return value.  use __stdcall calling convention

表示依赖 32 位调用约定

在 32 位 x86 中,stdcall 意味着所有 参数以相反的顺序传递到堆栈上(即最后一个参数首先被压入。也就是说,如果 arg[0] 位于addr 然后arg[1],不管是什么类型,都位于addr + sizeof(arg[0] ))。这就是您的示例中出现以下代码的原因:

// just copy the args buffer to the stack (it's already layed out correctly)
int* begin = m_argsBegin;
int* ptr = m_argsEnd;
int arr[1000], i=0;
while (ptr > begin) {
int val = *(--ptr);

__asm push val
}

实际上可以工作——因为它根本不重要到底是什么,参数是什么类型;所有相关的是它们中的每一个都在一个已知的内存位置,并且已知在内存中是连续的。如果您知道参数 N 位于 addr,那么您可以知道参数 N+1 位于 addr + sizeof(arg[ N]).

这就是评论所说的,“它已经正确布局” - 不幸的是,这在 64 位模式下是正确的。因此代码不能被“移植”;没有等同于端口。

至少部分基于寄存器的调用约定 - x64(64 位 x86)上的 Win64 表现不同。对于那些,它取决于被调用函数采用什么类型的参数(在 Windows 中,您可以在通用寄存器中传递四个整数类型参数以及在 XMM 寄存器中传递一些浮点类型参数)。因此,您需要更多了解您调用的函数的签名(原型(prototype)),而不仅仅是“它需要 N 个参数”,以便能够正确地编码来自像上面的“anycall”类型包装器。在 64 位模式下,对于您希望通过包装器调用的每个函数,您不仅需要知道总共有多少个参数,还需要知道通用 regs 中有多少,XMM< 中有多少 regs,以及堆栈中有多少。

“通过指针调用函数并将返回值复制到已知位置”部分是可移植的,可以用纯 C/C++ 表示。但是,如上所述,为此获取参数的部分不会以任何直接方式在 32 位 stdcall 和任何 64 位 x86 调用之间移植我知道的约定(无论是 Win64/x64 还是 UN*X x86_64 约定都不允许预测一个函数的所有参数的位置和总堆栈内存使用情况,只给定参数的数量和类型,但是不是他们的订单)。

您究竟需要做什么,更多取决于上述 class ExternalFunctionCall 的调用者/用户,而不是您展示的内联汇编的小样本。尤其有必要了解成员 m_argsBeginm_argsEnd 是如何初始化的以及在何处初始化。您能否提供更多有关该类的外观(所有成员变量/函数)的详细信息,以及有关其实际使用的示例?

关于c++ - 将内联汇编代码转换为 C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16142284/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com