January 05, 2014 Re: How do I choose the correct primative? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jake Thomas | 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 Re: How do I choose the correct primative? | ||||
---|---|---|---|---|
| ||||
Posted in reply to TheFlyingFiddle | 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 Re: How do I choose the correct primative? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jake Thomas | 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 Re: How do I choose the correct primative? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jake Thomas | Oh, and that was made from: int main() { int loadMe = 10; return loadMe; } |
January 07, 2014 Re: How do I choose the correct primative? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jake Thomas | 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 Re: How do I choose the correct primative? | ||||
---|---|---|---|---|
| ||||
Posted in reply to TheFlyingFiddle | > 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 |
Copyright © 1999-2021 by the D Language Foundation