Payload structure problem using inline asm

John Colvin john.loughran.colvin at gmail.com
Wed Jul 17 10:11:18 PDT 2013


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


More information about the Digitalmars-d-learn mailing list