使用读取 [ebp+4] 的 MSVC 内联 asm 移植到 64 位
Porting to 64-bit with MSVC inline asm that reads [ebp+4]
我在 Microsoft Visual Studio 2010 工作,我正在尝试为我的项目支持 64 位构建。据我所知,64 位架构不支持 __asm 关键字。
下面是项目仅支持 32 位构建时的工作原理。
void*
Class1::Class2::operator new(size_t size)
{
void *pCaller;
__asm mov edx, [ebp+4]
__asm mov pCaller, edx
char *pMem = (char *) malloc (sizeof(Class2) + size);
doSomething(pMem, pCaller);
void *ptr = (void *) (pMem + sizeof(Class2));
return(ptr);
}
我可以使用预处理器指令使上述功能取决于建筑类型。
void*
Class1::Class2::operator new(size_t size)
{
#ifndef _WIN64
void *pCaller;
__asm mov edx, [ebp+4]
__asm mov pCaller, edx
char *pMem = (char *) malloc (sizeof(Class2) + size);
doSomething(pMem, pCaller);
void *ptr = (void *) (pMem + sizeof(Class2));
return(ptr);
#elseif
// Accptable code for 64-bit project.
}
我必须以某种方式摆脱那些线条
__asm mov edx, [ebp+4]
__asm mov pCaller, edx
我以前从未遇到过汇编代码,但据我所知
__asm mov edx, [ebp+4]
是在寄存器之间移动数据,[ebp+4] 是函数调用 Class1::Class2::operator new(size_t size)
中定义的一些局部变量,存储在堆栈中。第二行只是在寄存器和内存之间移动数据。
如何用C/C++替换汇编代码?这甚至可能吗?
假设 EBP 设置为遗留帧指针(我认为 MSVC 内联 asm 强制),
[ebp+4]
持有 return 地址。 这段代码只是设置 void *pCaller = return_address
。
此代码只是保存分配内存的调用站点的地址。 (或者至少将其与内存块的地址一起传递给 doSomething
)。
这可能会阻止这个 operator new
内联到调用者中,所以删除它会很好。
如果您不需要这个(例如它只是调试基础设施),只需删除该部分并执行 malloc
来实现 operator new
.评论者建议现代调试工具可以为您完成此操作,从而使手动检测变得过时。
或者完全删除 new
和 delete
的重载 让它们使用默认的 C++ new
/ delete
.
或者显然 MSVC 有一个 _ReturnAddress()
intrinsic in intrin.h
用于 return 地址,所以如果你真的想继续这样做,你可以将它用于 32 位和 64 位代码而不是内联 asm。
请注意,在 MSVC 上,new
和 delete
与 malloc
/free
不兼容。 他们'使用单独的空闲列表 and/or 簿记格式重新分隔分配器。
因此,如果其他代码仍想在这些指针上使用 free()
,您确实需要为这个 class 保留重载的 new
/delete
,即使它不调用 doSomething
。并且您需要继续使用 malloc
而不是使用其他方式调用默认 new
.
但是如果唯一调用 free
的是相应的删除运算符,那么您的源代码中只有一个地方可以更改/删除。
我在 Microsoft Visual Studio 2010 工作,我正在尝试为我的项目支持 64 位构建。据我所知,64 位架构不支持 __asm 关键字。
下面是项目仅支持 32 位构建时的工作原理。
void*
Class1::Class2::operator new(size_t size)
{
void *pCaller;
__asm mov edx, [ebp+4]
__asm mov pCaller, edx
char *pMem = (char *) malloc (sizeof(Class2) + size);
doSomething(pMem, pCaller);
void *ptr = (void *) (pMem + sizeof(Class2));
return(ptr);
}
我可以使用预处理器指令使上述功能取决于建筑类型。
void*
Class1::Class2::operator new(size_t size)
{
#ifndef _WIN64
void *pCaller;
__asm mov edx, [ebp+4]
__asm mov pCaller, edx
char *pMem = (char *) malloc (sizeof(Class2) + size);
doSomething(pMem, pCaller);
void *ptr = (void *) (pMem + sizeof(Class2));
return(ptr);
#elseif
// Accptable code for 64-bit project.
}
我必须以某种方式摆脱那些线条
__asm mov edx, [ebp+4]
__asm mov pCaller, edx
我以前从未遇到过汇编代码,但据我所知
__asm mov edx, [ebp+4]
是在寄存器之间移动数据,[ebp+4] 是函数调用 Class1::Class2::operator new(size_t size)
中定义的一些局部变量,存储在堆栈中。第二行只是在寄存器和内存之间移动数据。
如何用C/C++替换汇编代码?这甚至可能吗?
假设 EBP 设置为遗留帧指针(我认为 MSVC 内联 asm 强制),
[ebp+4]
持有 return 地址。 这段代码只是设置 void *pCaller = return_address
。
此代码只是保存分配内存的调用站点的地址。 (或者至少将其与内存块的地址一起传递给 doSomething
)。
这可能会阻止这个 operator new
内联到调用者中,所以删除它会很好。
如果您不需要这个(例如它只是调试基础设施),只需删除该部分并执行 malloc
来实现 operator new
.评论者建议现代调试工具可以为您完成此操作,从而使手动检测变得过时。
或者完全删除 new
和 delete
的重载 让它们使用默认的 C++ new
/ delete
.
或者显然 MSVC 有一个 _ReturnAddress()
intrinsic in intrin.h
用于 return 地址,所以如果你真的想继续这样做,你可以将它用于 32 位和 64 位代码而不是内联 asm。
请注意,在 MSVC 上,new
和 delete
与 malloc
/free
不兼容。 他们'使用单独的空闲列表 and/or 簿记格式重新分隔分配器。
因此,如果其他代码仍想在这些指针上使用 free()
,您确实需要为这个 class 保留重载的 new
/delete
,即使它不调用 doSomething
。并且您需要继续使用 malloc
而不是使用其他方式调用默认 new
.
但是如果唯一调用 free
的是相应的删除运算符,那么您的源代码中只有一个地方可以更改/删除。