January 05, 2014
On Sunday, 5 January 2014 at 06:31:38 UTC, Jake Thomas wrote:
> And got 86,421 lines of assembly!! I expected a load instruction to load whatever was at loadMe's location into r0 (the return register) and not much else. Maybe 10 lines - tops - due to compiler fluffiness. I got about 8,641 times that - over 3 more orders of magnatude. What is going on here?

Well the compiler pulls in at minimum the entire D runtime if i'm not mistaken which make the standard .exe about 350kb.

Things like Object.factory also pulls in it's fair share due to not being able to remove classes. So we get alot of fluff in small programs.

The module layout of the standard library is also a problem, there is a lot of interconnections between the different modules in Phobos. (will hopefully be better when the modules are broken down into submodules)


I tested your test program on windows x64 and got the following result:

mov         ebp,esp
sub         rsp,10h
mov         eax,dword ptr [rbp-8]
lea         rsp,[rbp]
pop         rbp
ret

//This does a 32 bit load into the eax register (return register) from the //stack.
mov         eax,dword ptr [rbp-8]


//I also ran this to see if there was any difference
int main()
{
   int loadMe = 10;
   return loadMe;
}

--Resulting main functtion

 mov         ebp,esp
 sub         rsp,10h
 mov         eax,0Ah
 mov         dword ptr [rbp-8],eax
 lea         rsp,[rbp]
 pop         rbp
 ret

//Loads 10 the value to be returned and
//Then stores that value on the stack.
//While this is not rly necessary i ran
//the code in debug mode so it does not
//remove most useless instructions.
 mov         eax,0Ah
 mov         dword ptr [rbp-8],eax


//In optimized mode it is gone
 push        rbp
 mov         rbp,rsp
 mov         eax,0Ah
 pop         rbp
 ret

So it looks like dmd does 32-bit loads at least on windows x64.
January 06, 2014
On Sunday, 5 January 2014 at 08:23:45 UTC, TheFlyingFiddle wrote:
> On Sunday, 5 January 2014 at 06:31:38 UTC, Jake Thomas wrote:
>> And got 86,421 lines of assembly!! I expected a load instruction to load whatever was at loadMe's location into r0 (the return register) and not much else. Maybe 10 lines - tops - due to compiler fluffiness. I got about 8,641 times that - over 3 more orders of magnatude. What is going on here?
>
> Well the compiler pulls in at minimum the entire D runtime if i'm not mistaken which make the standard .exe about 350kb.
>
  Ah. Thank you for the explaination.

> Things like Object.factory also pulls in it's fair share due to not being able to remove classes. So we get alot of fluff in small programs.
>
  What do you mean by not being able to remove classes?

  Isn't the whole point of offering a language that has both structs, which
  can have functions, and classes to do away with classes when inheritence
  isn't needed?

> The module layout of the standard library is also a problem, there is a lot of interconnections between the different modules in Phobos. (will hopefully be better when the modules are broken down into submodules)
>
  I'm a big fan of 99% of D's specification, perhaps less a fan of its current implementation.
  But implementations hopefully change over time for the better. The hope is to one day simply re-compile the same source with a better compiler.
>
> I tested your test program on windows x64 and got the following result:
>
> mov         ebp,esp
> sub         rsp,10h
> mov         eax,dword ptr [rbp-8]
> lea         rsp,[rbp]
> pop         rbp
> ret
>
> //This does a 32 bit load into the eax register (return //register) from the stack.
> mov         eax,dword ptr [rbp-8]
>


What tools and parameters did you use to obtain that dissassembly?

I did not find "dword" anywhere in the dissassembly of my test program.

The last place I found eax used was this line:

  27:	2e 33 00             	xor    %cs:(%rax),%eax

Jake
January 06, 2014
Ok, I figured out how to use obj2asm. The trick is to cd to the directory holding the file you wish to dissassemble and _not_ specify the whole path, or else it throws a confusing "Fatal error: unrecognized flag" error.

I ran:

obj2asm intLoadTest.o intLoadTest.d > intLoadTest.s

and got this:


FLAT	group	
	extrn	_main
	public	_deh_beg
	public	_deh_end
	public	_tlsstart
	public	_tlsend
	public	_Dmain
	public	_D11intLoadTest12__ModuleInfoZ
	public	main
	extrn	_d_run_main
	extrn	_Dmain
	extrn	_d_dso_registry
.text	segment
	assume	CS:.text
.text	ends
.data	segment
_D11intLoadTest12__ModuleInfoZ:
	db	004h,010h,000h,000h,000h,000h,000h,000h	;........
	db	069h,06eh,074h,04ch,06fh,061h,064h,054h	;intLoadT
	db	065h,073h,074h,000h	;est.
.data	ends
.bss	segment
.bss	ends
.rodata	segment
.rodata	ends
.tdata	segment
_tlsstart:
	db	000h,000h,000h,000h,000h,000h,000h,000h	;........
	db	000h,000h,000h,000h,000h,000h,000h,000h	;........
.tdata	ends
.tdata.	segment
.tdata.	ends
.text._Dmain	segment
	assume	CS:.text._Dmain
_Dmain:
		push	RBP
		mov	RBP,RSP
		mov	EAX,0Ah
		pop	RBP
		ret
		0f1f
		add	[RAX],R8B
.text._Dmain	ends
.text.main	segment
	assume	CS:.text.main
main:
		push	RBP
		mov	RBP,RSP
		sub	RSP,010h
		mov	RDX,offset FLAT:_Dmain@64
		call	  _d_run_main@PC32
		leave
		ret
.text.main	ends
.data.d_dso_rec	segment
	db	000h,000h,000h,000h,000h,000h,000h,000h	;........
.data.d_dso_rec	ends
.text.d_dso_init	segment
	assume	CS:.text.d_dso_init
L0:		enter	0,0
		lea	RAX,_deh_end@PC32[RIP]
		push	RAX
		lea	RAX,_deh_beg@PC32[RIP]
		push	RAX
		lea	RAX,FLAT:[00h][RIP]
		push	RAX
		lea	RAX,FLAT:[00h][RIP]
		push	RAX
		lea	RAX,FLAT:.data.d_dso_rec[00h][RIP]
		push	RAX
		push	1
		mov	RDI,RSP
		call	  _d_dso_registry@PLT32
		leave
		ret
.text.d_dso_init	ends
	end

Can you tell whether a 32-bit load was used?

Jake

P.S - That's _way_ less output than what objdump gave!
January 06, 2014
Oh, and that was made from:

int main()
{
  int loadMe = 10;
  return loadMe;
}
January 07, 2014
On Monday, 6 January 2014 at 20:08:27 UTC, Jake Thomas wrote:
>> Things like Object.factory also pulls in it's fair share due to not being able to remove classes. So we get alot of fluff in small programs.
>>
>   What do you mean by not being able to remove classes?
>
>   Isn't the whole point of offering a language that has both structs, which
>   can have functions, and classes to do away with classes when inheritence
>   isn't needed?

Well since you could potentially create classes through Object.factory at runtime the code for unused classes will be compiled into the binary anyways this is even if you never use Object.factory directly in the code. I am not 100% sure but i think the main problem is ModuleInfo that keeps everything alive. And it keeps classes alive since they could be used by object factory. It also keeps other information like unittests locations and static constructors.

> What tools and parameters did you use to obtain that dissassembly?

I used the visual studio dissassembly window.


> Can you tell whether a 32-bit load was used?


_Dmain:
		push	RBP
		mov	RBP,RSP
		mov	EAX,0Ah
		pop	RBP
		ret



----   mov EAX,0AH

This is a 32-bit instruction. 64-bit instructions use the RAX register.

It's actually the same register but it's just named diffrently depending if you use the full 64-bits or just the lower 32-bits. It will automatically zero extend it.

See https://github.com/yasm/yasm/wiki/AMD64 for a simple intro into x64.
January 07, 2014
> Well since you could potentially create classes through Object.factory at runtime the code for unused classes will be compiled into the binary anyways this is even if you never use Object.factory directly in the code. I am not 100% sure but i think the main problem is ModuleInfo that keeps everything alive. And it keeps classes alive since they could be used by object factory. It also keeps other information like unittests locations and static constructors.
>

  Well then. I hope that changes for the better. It should be able to see that I'm not using the object factory or anything. Then again, the language has certain exceptions it is capable of throwing, which themselves are objects. I wonder if the garbage collector must retain the ability to throw an exception and thus retain the need of classes.

>> What tools and parameters did you use to obtain that dissassembly?
>
> I used the visual studio dissassembly window.
>
>

Thanks for the tip. Always nice to know about an assortment of tools.

>> Can you tell whether a 32-bit load was used?
>
>
> _Dmain:
> 		push	RBP
> 		mov	RBP,RSP
> 		mov	EAX,0Ah
> 		pop	RBP
> 		ret
>
>
>
> ----   mov EAX,0AH
>
> This is a 32-bit instruction. 64-bit instructions use the RAX register.
>
> It's actually the same register but it's just named diffrently depending if you use the full 64-bits or just the lower 32-bits. It will automatically zero extend it.
>
> See https://github.com/yasm/yasm/wiki/AMD64 for a simple intro into x64.

Excellent! We successfully proved that it does use 32-bit load instructions in a 64-bit binary, both for Linux and Windows!

Good to know about RAX/EAX, thanks - I was only familiar with ARM assembly.
There is CISC in this world, apparently.


For the full experience, I disassembled the binary from the following:

/*
  I always do int mains - except when trying to simplify assembly as much as possible for educating myself about instructions the compiler outputs. I never even ran this binary, I only made it to look at its disassembly.
*/
void main()
{
  longLoadTest();
}

long longLoadTest()
{
  long loadMe = 10;
  return loadMe;
}

  Sure enough, I saw something very similar to what you pointed out, but using the RAX name instead of the EAX name (for longLoadTest's return).

Thank you very much,
Jake
1 2
Next ›   Last »