使用读取[EBP 4]的MSVC内联ASM移植到64位



我在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 Inline ASM力量(,
[ebp+4]保留返回地址。此代码只是设置void *pCaller = return_address

此代码只是保存分配内存的呼叫点的地址。(或至少将其与内存块的地址一起传递到doSomething(。

这可能会阻止此operator new插入呼叫者,因此删除这将是不错的。


如果您不需要此(例如,只是调试基础架构(,只需删除该部分,然后执行malloc来实现operator new。评论者建议现代调试工具可以为您做到这一点,使手动仪器过时。

或删除newdelete的过载,完全让他们使用默认的C new/delete

或显然MSVC在返回地址中具有_ReturnAddress()的 CC_12固有性,因此您可以在32位和64位代码中使用它,而不是Inline ASM,如果您真的想继续这样做。

>

请注意,在MSVC上,newdeletemalloc/free不兼容。它们是单独的分配器,带有单独的免费列表和/或簿记格式。

因此,如果其他代码仍然希望在这些指针上使用free(),则即使不调用doSomething,您也需要将其过载的new/delete保留。而且您需要继续使用malloc,而不是使用其他方式调用默认的new

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

最新更新