Reputation: 372
I'm working in Microsoft Visual Studio 2010, and I'm trying to support 64-bit build for my project. And from what I can tell 64-bit architecture is not support __asm keyword.
So here is how it worked when project only supported 32-bit build.
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);
}
I can use preprocessor directives to make above function depend on building type.
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.
}
I must somehow get rid of those lines
__asm mov edx, [ebp+4]
__asm mov pCaller, edx
I have never encounter assembly code before, but from what I can tell
__asm mov edx, [ebp+4]
is moving data between registers, [ebp+4] is some local variable defined inside function calling Class1::Class2::operator new(size_t size)
stored on stack. The second line is simply moving data between register and memory.
How can I replace assembly code with C/C++? Is this even possible?
Upvotes: 1
Views: 1020
Reputation: 365332
Assuming that EBP is set up as a legacy frame-pointer (which MSVC inline asm forces, I think),
[ebp+4]
holds the return address. This code is just setting void *pCaller = return_address
.
This code is just saving the address of the call-site that's allocating the memory. (Or at least passing it to doSomething
, along with the address of the memory block).
This may be stopping this operator new
from inlining into callers, so removing that would be nice.
If you don't need this (e.g. it's just debugging infrastructure), simply remove that part and just do the malloc
to implement operator new
. Commenters suggest that modern debugging tools can do this for you, making manual instrumentation obsolete.
Or remove the overloads of new
and delete
entirely to let them use the default C++ new
/ delete
.
Or apparently MSVC has a _ReturnAddress()
intrinsic in intrin.h
for the return address, so you can use that for both 32 and 64-bit code instead of inline asm if you really want to keep doing this.
Note that on MSVC, new
and delete
aren't compatible with malloc
/free
. They're separate allocators with separate free-lists and/or bookkeeping formats.
So if other code still wants to use free()
on these pointers, you do need to keep the overloaded new
/delete
for this class even if it doesn't call doSomething
. And you need to keep using malloc
instead of using some other way of calling the default new
.
But if the only thing that was calling free
is the corresponding delete operator, you only have one place in your source to change / remove.
Upvotes: 5