使用读取 [ebp+4] 的 MSVC 内联汇编移植到 64 位

XYZ*_*123 1 c++ porting x86-64 inline-assembly visual-c++

我正在使用 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);
}
Run Code Online (Sandbox Code Playgroud)

我可以使用预处理器指令使上述函数取决于建筑类型。

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.
}
Run Code Online (Sandbox Code Playgroud)

我必须以某种方式摆脱这些线条

__asm mov edx, [ebp+4] 
__asm mov pCaller, edx 
Run Code Online (Sandbox Code Playgroud)

我以前从未遇到过汇编代码,但据我所知

__asm mov edx, [ebp+4]
Run Code Online (Sandbox Code Playgroud)

在寄存器之间移动数据,[ebp+4]是Class1::Class2::operator new(size_t size)存储在堆栈上的函数调用内部定义的一些局部变量。第二行只是在寄存器和内存之间移动数据。

如何用 C/C++ 替换汇编代码?这可能吗?

Pet*_*des 5

假设 EBP 设置为遗留帧指针(我认为这是 MSVC 内联汇编强制的),
[ebp+4]保存返回地址。 这段代码只是设置void *pCaller = return_address

这段代码只是保存分配内存的调用站点的地址。(或者至少将其doSomething与内存块的地址一起传递给 )。

这可能会阻止它operator new内联到调用者中,所以删除它会很好。


如果您不需要这个(例如,它只是调试基础设施),只需删除该部分并执行即可malloc实现operator new。评论者建议现代调试工具可以为您做到这一点,从而使手动检测变得过时。

或者完全删除new和的重载,delete让它们使用默认的 C++ new/ delete

或者显然 MSVC 有一个_ReturnAddress()内在的intrin.h返回地址,因此如果您确实想继续这样做,您可以将其用于 32 位和 64 位代码,而不是内联汇编。


请注意,在 MSVC 上,new和与/delete不兼容。mallocfree 它们是具有单独空闲列表和/或簿记格式的单独分配器。

因此,如果其他代码仍然想在这些指针上使用free(),您确实需要保留此类的重载new/ ,即使它不调用. 并且您需要继续使用而不是使用其他调用默认值的方式。deletedoSomethingmallocnew

但是,如果唯一调用的free是相应的删除运算符,则源中只有一个位置可以更改/删除。