Payload structure problem using inline asm

Baz burg.basile at yahoo.com
Wed Jul 17 11:04:34 PDT 2013


On Wednesday, 17 July 2013 at 17:11:20 UTC, John Colvin wrote:
> On Wednesday, 17 July 2013 at 17:09:30 UTC, John Colvin wrote:
>> On Wednesday, 17 July 2013 at 16:52:40 UTC, Baz wrote:
>>> Hello, I've defined a simple template used in a double linked 
>>> list implementation:
>>>
>>> template tDLListItem(T)
>>> {
>>> 	const cPrevOffs = size_t.sizeof;
>>> 	const cNextOffs = size_t.sizeof + size_t.sizeof;
>>> 	void* NewItemCaps(T* aData, void* aPrevious, void* aNext)
>>> 	{
>>> 		auto lPt = std.c.stdlib.malloc( 3 * size_t.sizeof );
>>> 		if (!lPt)
>>> 		{
>>> 			throw new OutOfMemoryError();
>>> 		}
>>> 		*cast(size_t*)  lPt = cast(size_t) aData;
>>> 		*cast(size_t*) (lPt + cPrevOffs) = cast(size_t) aPrevious;
>>> 		*cast(size_t*) (lPt + cNextOffs) = cast(size_t) aNext;
>>> 		return lPt;
>>> 	}
>>> 	void DeleteItemCaps(void* aItemCaps)
>>> 	{
>>> 		std.c.stdlib.free(aItemCaps);
>>> 	}
>>> 	void SetItemCapsPrev(void* aItemCaps, void* aPrevious)
>>> 	{
>>> 		*cast(size_t*) (aItemCaps + cPrevOffs) = cast(size_t) 
>>> aPrevious;
>>> 	}
>>> 	void SetItemCapsNext(void* aItemCaps, void* aNext)
>>> 	{
>>> 		*cast(size_t*) (aItemCaps + cNextOffs) = cast(size_t) aNext;
>>> 	}
>>> 	void SetItemCapsData(void* aItemCaps, T* aData)
>>> 	{
>>> 		*cast(size_t*) aItemCaps = cast(size_t) aData;
>>> 	}
>>> 	T* GetItemCapsData(void* aItemCaps)
>>> 	{
>>> 		version(X86) asm
>>> 		{
>>> 			naked;
>>> 			mov     EAX, [EAX];
>>> 			ret;
>>> 		}
>>> 		else version(none) asm
>>> 		{
>>> 			naked;
>>> 			mov     RAX, [RAX];
>>> 			ret;
>>> 		}
>>> 		else
>>> 		{
>>> 			return *cast(T**) (aItemCaps);
>>> 		}
>>> 	}
>>> 	void* PreviousItemCaps(void* aItemCaps)
>>> 	{
>>> 		version(X86) asm
>>> 		{
>>> 			naked;
>>> 			mov     EAX, [EAX + cPrevOffs];
>>> 			ret;
>>> 		}
>>> 		else version(none) asm
>>> 		{
>>> 			naked;
>>> 			mov     RAX, [RAX + cPrevOffs];
>>> 			ret;
>>> 		}
>>> 		else
>>> 		{
>>> 			return *cast(size_t**) (aItemCaps + cPrevOffs);
>>> 		}
>>> 	}
>>> 	void* NextItemCaps(void* aItemCaps)
>>> 	{
>>> 		version(X86) asm
>>> 		{
>>> 			naked;
>>> 			mov     EAX, [EAX + cNextOffs];
>>> 			ret;
>>> 		}
>>> 		else version(none) asm
>>> 		{
>>> 			naked;
>>> 			mov     RAX, [RAX + cNextOffs];
>>> 			ret;
>>> 		}
>>> 		else
>>> 		{
>>> 			return *cast(size_t**) (aItemCaps + cNextOffs);
>>> 		}
>>> 	}
>>> }
>>>
>>> It's used as a struct. (BTW I call the "payload" a "capsule", 
>>> a "caps"). In x86 (tested on win) I can optimize the access 
>>> into the "capsule" to a simple member (I return the data 
>>> pointed by the parameter by digging using the param + 
>>> memberoffset as an address...
>>>
>>> But it doesn't work in x86_64 (tested on nux). What's wrong 
>>> with that ? Does I miss something in the parameters 
>>> convention/ABI for x64 (that's why the x64 versions are 
>>> surounded by version(none) instead of version (X86_64) )) ?
>>>
>>> Does dmd produce real x86_64 code or is it possible for a 64 
>>> bit appli to work with 32 bit pointers ?
>>> (I know this Q coulds look weird but I've already seen some 
>>> false x86_64 while doing some static analysis)
>>>
>>> WTF.MEH.
>>
>> AFAIK on windows dmd uses the optlink calling convention, so 
>> the 1st argument is in EAX
>>
>> On linux 32bit (cdecl) the first argument will be on the top 
>> of the stack.
>>
>> On linux 64bit (system V) the first argument will be in RDX
>>
>> see:
>> http://en.wikipedia.org/wiki/X86_calling_conventions
>> or find a copy of the system V abi docs somewhere.
>
> big woops there, linux x64 arguments are RDI first, not RDX
> The order is RDI RSI RDX RCX R8 R9

Thx. I'll test that. My initial x86_64 implementation was based 
on a wrong assumption...(that rax is used as eax for 
parameters...).


More information about the Digitalmars-d-learn mailing list