www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - asm stackframe question

reply "Stefan" <stefan schuerger.com> writes:
As a little learning exercise for D I’m writing a fixed point 
library. Part of this is checking standard integer operations for 
overflows.

This is the code for adding 2 longs:

int64 add64ov(int64 a, int64 b) {
	int64 res;
	 asm {
		mov EAX,a    ;
		mov EDX,a+4  ;
		add EAX,b    ;
		adc EDX,b+4  ;
		jo  overflow ;
		mov res,EAX  ; // Not optimal: cannot do a ret here because of 
stack frame previously not correctly set
		mov res+4,EDX;
	}
	return res;
	overflow:
	throw new OverflowException("Overflow in 64 bit addition");
}

The detour via the res variable is costly; the standard epilogue
(I probably need a frame pointer for the exception throw to work):
   mov ESP, EBP
   pop EBP
   ret

creates an access violation.

Ideas, anyone?
Apr 07 2012
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Stefan:

 Ideas, anyone?

Use the "naked" attribute and do it all by yourself? Keep also in mind that D functions that contain ASM don't get inlined in DMD (and probably elsewhere too). Bye, bearophile
Apr 07 2012
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 04/08/2012 12:13 AM, Stefan wrote:
 As a little learning exercise for D I’m writing a fixed point library.
 Part of this is checking standard integer operations for overflows.

 This is the code for adding 2 longs:

 int64 add64ov(int64 a, int64 b) {
 int64 res;
 asm {
 mov EAX,a ;
 mov EDX,a+4 ;
 add EAX,b ;
 adc EDX,b+4 ;
 jo overflow ;
 mov res,EAX ; // Not optimal: cannot do a ret here because of stack
 frame previously not correctly set
 mov res+4,EDX;
 }
 return res;
 overflow:
 throw new OverflowException("Overflow in 64 bit addition");
 }

 The detour via the res variable is costly; the standard epilogue
 (I probably need a frame pointer for the exception throw to work):
 mov ESP, EBP
 pop EBP
 ret

 creates an access violation.

 Ideas, anyone?

The D calling convention leaves stack cleanup up to the callee. Either mark your function as extern(C) or use leave ret 16 The second option might not be portable across all currently available compilers though.
Apr 07 2012
prev sibling next sibling parent "Stefan" <stefan schuerger.com> writes:
On Sunday, 8 April 2012 at 01:15:48 UTC, Timon Gehr wrote:

 The D calling convention leaves stack cleanup up to the callee. 
 Either mark your function as extern(C) or use

 leave
 ret 16

 The second option might not be portable across all currently 
 available compilers though.

Hi Timon, Works fine, thanks! I don't worry too much about compatibility - GCD uses a completely different ASM notation anyway. Cheers, Stefan
Apr 08 2012
prev sibling next sibling parent "Stefan" <stefan schuerger.com> writes:
On Saturday, 7 April 2012 at 23:50:42 UTC, bearophile wrote:
 Use the "naked" attribute and do it all by yourself?

Then I would also have to do the throw a) fully by myself (with mangling, etc), or b) at least get the stack frame in order so that the throw finds the stack the way it expects...
 Keep also in mind that D functions that contain ASM don't get 
 inlined in DMD (and probably elsewhere too).

Yes, but I don't have much of a choice here... Cheers, Stefan
Apr 08 2012
prev sibling parent "Stefan" <stefan schuerger.com> writes:
On Saturday, 7 April 2012 at 23:50:42 UTC, bearophile wrote:
 Keep also in mind that D functions that contain ASM don't get 
 inlined in DMD (and probably elsewhere too).

BTW: The GCC backend has a pretty powerful ASM support where inlining IS possible and you can simply say things like 'give me a free register which supports the XYZ operation' and the backend optimizer does the register juggling (such as saving any used registers on the stack first or choosing a free one) for you - which is essential for sensible inlining. OK, that's not of much use on an architecture with a feeble register set such as i386, but it's a pretty powerful feature with architectures with lots of general registers such as m68k or SPARC. But I'm drifting off... Cheers, Stefan
Apr 08 2012