我在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
。评论者建议现代调试工具可以为您做到这一点,使手动仪器过时。
或删除new
和delete
的过载,完全让他们使用默认的C new
/delete
。
或显然MSVC在返回地址中具有_ReturnAddress()
的 CC_12固有性,因此您可以在32位和64位代码中使用它,而不是Inline ASM,如果您真的想继续这样做。
请注意,在MSVC上,new
和delete
与malloc
/free
不兼容。它们是单独的分配器,带有单独的免费列表和/或簿记格式。
因此,如果其他代码仍然希望在这些指针上使用free()
,则即使不调用doSomething
,您也需要将其过载的new
/delete
保留。而且您需要继续使用malloc
,而不是使用其他方式调用默认的new
。
但是,如果唯一调用free
的是相应的删除操作员,则在源中只有一个位置可以更改/删除。