Hi All,
i'm trying to make a simple "hello world" program as small as possible, currently i'm stuck on 1kb, but i have a lot of empty bytes in it..
how can i get rid of these binary 0's ?
here's the program: http://www.white-scorpion.nl/testjunk/hello.zip
i have no source since i made an empty program in masm:
.586
.model flat,stdcall
option casemap:none
.code
start:
mov eax,eax
end start
and started writing my code in it using ollydbg (http://home.t-online.de/home/Ollydbg/). it has no data section, and the data is in the code section as well (this forced me to make the code section writable).
so now i have a program of 124 bytes of code, but a program of 1024 bytes, how can i get rid of as much as possible from the other 900 bytes? i know i have to have bytes reserved for the PE header and DOS stub, but still i think it should be possible to strip off about 350 bytes of of the code section.
Any ideas?
Thanks in advance!
Hi white scorpion,
There are some tricks to create very small Win32 executables but the minimum size for an executable is 1024 bytes according to MS.
An example:
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.code
MsgCaption db "Iczelion's tutorial no.2",0
MsgBoxText db "Win32 Assembly is Great!",0
start:
invoke MessageBox, NULL,addr MsgBoxText, addr MsgCaption, MB_OK
invoke ExitProcess,NULL
END start
\masm32\bin\ml /c /coff Msgbox.asm
\masm32\bin\polink /SUBSYSTEM:WINDOWS /MERGE:.data=.text Msgbox.obj
\masm32\bin\polink /SUBSYSTEM:WINDOWS /MERGE:.data=.text /ALIGN:4 /OUT:Msgbox2.exe Msgbox.obj
The first one is 1024 bytes where the second executable is only 680 bytes with the minimum alignment value. You can get even smaller executables with some extra modifications but EXEs under 1024 bytes may not run on every version of Windows.
[attachment deleted by admin]
White Scorpion,
Another point to remember is this; even if you could make the file smaller than 1024 bytes, it will still occupy 1024 bytes no matter what size it is. A data file of 20 bytes, for instance, uses 1024 bytes of storage space because of the way disk writes are handled. The only time such savings can be realized is in memory.
Paul
It's possible to program a .com executable for the smallest bytewise footprint.
Regards, P1 :8)
@vortex > thanks, i never thought of that, i'll go and work it out ;)
@pbrennick > i know, on my system it is even 32kb since i'm using larger sections on my hdd to improve speed with NTFS, but it's just the challenge to make it as small as possible ;)
@P1 > this then wouldn't be a 32-bit app, would it? i know i can make a smaller program using 16-bit assembly, but my challenge (i gave myself) is to make the smallest 32-bit hello world program possible since it would help me improve my understandings of the PE file format in a practical manner...
Scorpion,
The problem is that the PE spec requires one section of 512 bytes for the MZ and PE header and section headers and at least 1 more for any minimal code and for it to be a legal PE file, it is at the minimum 2 x 512 byte sections. There are enough examples of 1k EXE files so you cannot do it any smaller without making a file that does not properly comform to the PE specifications. Some of them will run on some versions of Windows but unless they properly comform to the specification, there are other versions they will not run on.
I have seen manually coded "PE" files down to a couple of hundred bytes but they sufer the same problem as any of the non standard ones.
Quote from: white scorpion on March 29, 2005, 10:49:27 AM@P1 > this then wouldn't be a 32-bit app, would it?
As long as M$ permits a .com to execute in a 32bit environment. It's a 32bit app, when it takes advantage of that environment.
Research your options. I have battled with 32bit .com files before.
Regards, P1 :8)
IMHO, I don't see why making an "hello word" program which takes 1k (for .exe size) is something to try and "achieve". You are still loading the .DLL runtime (kernel32, etc) which take upwards of 512k to 1meg of MEMORY for just a little app that does nothing.
In my view, why create code size that is SO small when in reality, you want code which runs FAST. So what if it takes a few K more to run .
Just my opinion.
Relvinian
QuoteScorpion,
The problem is that the PE spec requires one section of 512 bytes for the MZ and PE header and section headers and at least 1 more for any minimal code and for it to be a legal PE file, it is at the minimum 2 x 512 byte sections. There are enough examples of 1k EXE files so you cannot do it any smaller without making a file that does not properly comform to the PE specifications. Some of them will run on some versions of Windows but unless they properly comform to the specification, there are other versions they will not run on.
I have seen manually coded "PE" files down to a couple of hundred bytes but they sufer the same problem as any of the non standard ones.
this is more like i meant, i know i should have 1kb minimum, but i think stripping a piece of the dos stub should be possible as well. all i want is that it still can be executed, i don't care about other windows versions since i wouldn't ever going to distribute it (who cares about such a program?).
QuoteAs long as M$ permits a .com to execute in a 32bit environment. It's a 32bit app, when it takes advantage of that environment.
Research your options. I have battled with 32bit .com files before.
Regards, P1
i never knew this, i was under the impression that the .com files were run under the dos-emulator instead of running under a true 32-bit environment... i will do some research about this..
@Relvinian> who cares if you can write a very fast hello world program? i know speed most of the time is most important, but sometimes it isn't, and in this case, like stated before, i just want to do this to learn more about the PE format in a practical manner. this means stripping off as many as possible but still being able to run the program. i don't care if this program would use about 5mb of memory, all i care atm is the size on disk.
like i said, it is not something what would really help me improve my programming skills, but it does improve my understanding on what is really necessary and what isn't really necessary in a PE file.
eventually i will try to learn to write a program in a hexeditor, without having to use any assembler anymore, but this will take a lot of time since i would have to memorize all opcodes and their hexvalues....
Quote from: Relvinian on March 29, 2005, 04:57:55 PM
IMHO, I don't see why making an "hello word" program which takes 1k (for .exe size) is something to try and "achieve". You are still loading the .DLL runtime (kernel32, etc) which take upwards of 512k to 1meg of MEMORY for just a little app that does nothing.
That's why it become prudent to ask why, when you can not figure out why. Size does matter in an e-mail attachment encoded and mass mailed.
Regards, P1 :8)
QuoteThat's why it become prudent to ask why, when you can not figure out why. Size does matter in an e-mail attachment encoded and mass mailed.
Regards, P1 Cool
well thats certainly true, but that surely isn't my intention :lol:
like i said, i love challenges, and for me this is a challenge... just as writing a program from scratch using a hexeditor is a challenge, but this might take a while to achieve ;)
Hi white scorpion,
I got a Win32 MessageBox in 232 bytes: http://members.home.nl/ruurd.wiersma/ under Assembler.
The trick is to compress the file. Uncompressed size = 576 bytes, compressed size = 116 bytes.
I needed to store an uncompressor in front, size = 116 bytes, for a total of 232 bytes.
The uncompressor makes a temporary file, but performance was not an issue, right?
As to the usefulness of this project: I learned a lot about the PE format and about assembler.
there is a 32bytes version:
Start-->Execute:
rundll32 User32,MessageBox HELLO
:bg
Quote from: mariø on April 01, 2005, 04:27:39 PM
there is a 32bytes version:
Start-->Execute:
rundll32 User32,MessageBox HELLO
:bg
:P
Even more smaller : save the code below as small.vbs , only 21 bytes :
Msgbox "Hello"
Hehe, VBscript. I don't think that counts.
Quote
I learned a lot about the PE format and about assembler.
Not enough apparently.
Your file doesn't work here under windows xp.
DEBUG.EXE is already installed on WIN98 to WINXP, I believe. And it's free, and a lot of the older programming books mention it, and how to use it. But it is pretty simple.
You can make .com files with this too. (I think someone else mentioned this earlier).
I've even made graphics .com files recently that were only a couple 100 bytes or so.
Later guy,
Jeff C
:U
P.S. You mentioned mass mailing emails of this small program, don't be making no viruses now...
Hi,
I have got bored of everything else. Right now I am working on making a working PE execuatble using a hex editor. Its going pretty well. First I will make a file with only a RET. Then add an ExitProcess, and then an MessageBox. THe funny thing is I put somedummy value in the linker version field of the PE header and a file analyser program tells me it is packed with Morphine!! :dazzled: I am going to try changing this value to see what happens.
Thomas
exitprocess isn't required.
No.
At first there is no ExitProcess. Only a RET. Then I add ExitProcess to learn adding Import table. I am still working on it. I have a doubt though. I know that when we call an API function which goes to a jump table with jmp dword ptr[XXXXXXXX]
So what should this XXXXXXX point to? The FirstThunk member of the Import Descriptor?
Thomas
The correct dword located within the IAT.
The jmp isn't necessary either.
But without an import, the exe will not run on win2k. So you need an import if you want your exe to run in win2k. Usually the best function to call is still ExitProcess.
But without an import, the exe will not run on win2k. So you need an import if you want your exe to run in win2k. Usually the best function to call is still ExitProcess.
No, PE executables don't require an import table.
EXitProcess only is useful if you forget to close opened files, you've created one more or several threads or if some used dlls you're using need to perform some special operations on DLL_PROCESS_DETACH/DLL_THREAD_DETACH.
hitchhikr,
Did you try to run executables without import section on Win2K?
Did you ?
If this continues to devolve into an argument, I will pull the plug.
Paul
I am stating a well-known fact. I am very sure about it as I used to own a win2k. There are tools that fix exe that have no import tables so that it would run in win2k. The pe loader for win2k is just different (extremely picky) from the pe loader found on other windows.
And I don't intend this to be an argument.
Quoting f0dder from win32asmcommunity board
QuoteYou must make sure kernel32 is mapped in your process, otherwise your process won't load on all win32 versions (win2k, for instance).
Folks,
Plase keep debates !!! OUT !!! of the Campus, its for programmers learning assembler, not an arena for extended argument.
Quote from: hitchhikr on April 02, 2005, 12:15:04 PM
The correct dword located within the IAT.
The jmp isn't necessary either.
Which is this 'correct DWORD'?
Thomas
I'll look around this week, and see if I can find any of my DEBUG made .com programs, and upload them here, the Hello World, I think it's like 32 bytes, most of that being the Hello World string statement itself.
.com files are SMALL.
Later,
Jeff C
:bdg
P.S. If you want to see the display, you have to be in command-line also, the programs I made executed in a split second, and then were gone!!!
Hi,
This is a problem I found with most tutorials that talk about import tables. They forget to mention that the IAT DAta Directory should point to the array of RVA's of IMAGE_THUNK_DATAs . I found out that the API calls point to a member of this array.
Thomas
One's goal should never be to write the "world's smallest 32-bit 'Hello World' program." Instead, see how much functionality you can pack into 4K. After all, under 32-bit OSes 4,096 bytes of code space is the *minimum* amount of memory your process will consume (it will also consume 4K of stack space, and possibly some data space, too). Yes, you might make the EXE file a little smaller, but when you consider that most recent versions of Windows generally allocate 4K chunks on the disk, too, that magic number appearing in the directory listing, if it's not a multiple of 4K, is a total lie.
Learning how to create a tiny "Hello World" program is a fascinating side trip in terms of code compaction, but the truth is that the application is too small to allow you to learn really useful techniques (you need to work on larger programs to get a good feel for how to write compact code). And given the memory page requirements of the x86/Windows combination, and cluster sizes on disk, you're wasting your time trying to compact something that's already below the limits imposed externally to your program.
As I said, a better goal is to see how much functionality you can cram into 4K.
Cheers,
Randy Hyde
If one wants to cram as much as possible into 4k one have to first perfectly understand the PE file format and make this part of the file as small or as highly compressible as possible.
I agree. A good challenge would be to find a program and attempt to compress it as much as possible. Perferably a program that interests you.
Randall is right, better is to study to improve the functionality.
Quote from: hitchhikr on April 04, 2005, 11:16:33 PM
If one wants to cram as much as possible into 4k one have to first perfectly understand the PE file format and make this part of the file as small or as highly compressible as possible.
As long as the whole file sits in a single disk block (generally 4K), compression is irrelevant. It's like squeezing a bunch of extra cycles out of a code sequence that executes once during initialization -- it doesn't buy you much.
Knowing the PE file format isn't a bad thing, but knowing the PE format doesn't really help you write better assembly code. When someone says something like "I want to write the world's smallest 'hello world' program" the assumption is that they want to do this by using the fewest number of instructions (or the shortest sequence of bytes to comprise those instructions), not by resorting to compression or other techniques that are independent of the original purpose.
When people suggest "compression" as a solution to the "shortest hello world" program I have to laugh. Such people have completely missed the point of the exercise -- to learn how to write *code* as compactly as possible. When it's all said and done, the compression approach is actually *larger* because you have to supply the code to decompress the actual executable. While compressed EXEs do serve a purpose (for *large* application), their application to the "hello world" example defeats the purpose.
As usual, I still argue that the smallest memory block you can allocate is 4K. Trying to shrink an application below this point is, well, pointless. Further, as any win32 app is going to have to link with Kernel32.dll (and, possibly, others), the size of the file doesn't really have much meaning as all the real work is being done by a DLL elsewhere. You may as well bury the string in a user-written DLL and write a "hello world" program consisting of a single call to the DLL and make claims about the size of your code.
"The world's shortest 'Hello World' program" actually made sense in the days of DOS and COM files where the program would clear the (text) video display and copy the string "Hello World" directly into video memory. COM files could be as small as disk blocks (typically 512 bytes, in those days) and the application only used as much memory as it's code, stack, and data segments required (well, you could argue that DOS apps always consumed the whole 640K because there was no multitasking, but that's a different issue).
Again, my argument is that a trival applicaton like "Hello World" provides almost no opportunity for real code compaction techniques. A better solution is to pick a memory size and see how much functionality you can squeeze into that, rather than taking a trival program and seeing how small you can make it. There have been several "256-byte" contests floating around. I still argue that 4K is the right size, as this is the page size of the x86.
To this date, one of the best examples of packing functionality into a limited amount of space I've seen is the original Apple II monitor ROM. Steve Wozniak (Woz) packed an *incredible* amount of functionality into 2K of memory. Amazing stuff.
Cheers,
Randy Hyde
I think you missed the point by a few hundred miles, Hyde.
Quote
Knowing the PE file format isn't a bad thing, but knowing the PE format doesn't really help you write better assembly code. When someone says something like "I want to write the world's smallest 'hello world' program" the assumption is that they want to do this by using the fewest number of instructions (or the shortest sequence of bytes to comprise those instructions), not by resorting to compression or other techniques that are independent of the original purpose.
Well...
Quote
If one wants to cram as much as possible into 4k one have to first perfectly understand the PE file format and make this part of the file as small or as highly compressible as possible.
Where did i even slightly mentioned that it might helps someone to write better code ?
Quote
When people suggest "compression" as a solution to the "shortest hello world" program I have to laugh.
And what offending imbecile would suggest such heresy ?
Quote
When it's all said and done, the compression approach is actually *larger* because you have to supply the code to decompress the actual executable. While compressed EXEs do serve a purpose (for *large* application), their application to the "hello world" example defeats the purpose.
Of course, plain PE files compression without using dos/cab droppers becomes effective for programs with size of a few kilobytes (around 4).
Notice that you're the only one still talking about that hello world stuff, bub.
QuoteOne's goal should never be to write the "world's smallest 32-bit 'Hello World' program." Instead, see how much functionality you can pack into 4K. After all, under 32-bit OSes 4,096 bytes of code space is the *minimum* amount of memory your process will consume (it will also consume 4K of stack space, and possibly some data space, too). Yes, you might make the EXE file a little smaller, but when you consider that most recent versions of Windows generally allocate 4K chunks on the disk, too, that magic number appearing in the directory listing, if it's not a multiple of 4K, is a total lie.
Learning how to create a tiny "Hello World" program is a fascinating side trip in terms of code compaction, but the truth is that the application is too small to allow you to learn really useful techniques (you need to work on larger programs to get a good feel for how to write compact code). And given the memory page requirements of the x86/Windows combination, and cluster sizes on disk, you're wasting your time trying to compact something that's already below the limits imposed externally to your program.
As I said, a better goal is to see how much functionality you can cram into 4K.
Cheers,
Randy Hyde
that would indeed be interesting indeed, but i have to start somewhere, and this was the first thing that came to mind... i'm already reading up on compressions of PE files, but this most of the time needs an uncompressor as well, and this is something i am trying to avoid...
and yes of course i would always want to improve my writing skills, but IMO this can only be done by experimenting and learning.
Unfortunately i didn't have the time to respond sooner since i've been very busy learning to write device drivers :)
Here is one way to save bytes that I see all the time in Win32 DLLs:
Instead of cmp eax,0 use:
xor edi,edi
cmp eax,edi
Or even instead of cmp eax,1 use
xor edi,edi
inc edi
cmp eax,edi
Quote from: AeroASM on April 22, 2005, 08:52:49 PM
Here is one way to save bytes that I see all the time in Win32 DLLs:
Instead of cmp eax,0 use:
xor edi,edi
cmp eax,edi
Or even instead of cmp eax,1 use
xor edi,edi
inc edi
cmp eax,edi
test eax, eax
jz/jnz
dec eax
jz/jnz
Yeah, yeah, make me look stupid why don't you?
No, that's not my point. I am not attacking you or anything - I have no reason to do so. I don't if you are correct - maybe C compilers are not that great at optimising. The examples you stated actually take up more space.
cmp eax, 0 = 83h F8h 00h
xor edi, edi = 33h FFh
cmp eax, edi = 3Bh C7h
test eax, eax = 85h C0h
------------------------------------
cmp eax, 1 = 83h F8h 01h
xor edi, edi = 33h FFh
inc edi = 47h
cmp eax, edi = 3Bh C7h
dec eax = 48h
Sorry - I was not being serious. I found it funny (as in "ha ha") that after I try to make a really intelligent comment to add to the discussion, someone else completely smashes it down.
Anyway, if that is the the case either Microsoft programmers are stupid or they use idiotic compilers.
hi guys,
it is not worth making smaller code since it is difficult enough to get below the 1kb as discussed previously in the thread.. i'm sure if it is possible to remove the not used space in the sections you can safe a lot more then a few bytes with the optimizing opcodes. don't get me wrong, it is interesting indeed, but in this case it is something which should be done last, at first i need to strip off as much unused bytes as possible....
Quote from: AeroASM on April 22, 2005, 08:52:49 PM
Instead of cmp eax,0 use:
xor edi,edi
cmp eax,edi
There is also:-
OR EAX,EAX
which does the same as CMP EAX,0
The pursuit of size reduction in an exe file by code size minimisation has always made me laugh. A toy of mine called TheGun was an example of size reduction by any method possible including compression but apart from normal minimum code to perform the task, the successful methods were in architecture, not chasing bytes in code.
I once spent a couple of hours on a copy of TheGun doing every trick to reduce the code size even further, register replacements for immediate variables and the like and at the end of the effort, I could not get its size down by a single 512 byte section. Now it already has all of the dirty tricks, no DATA section, all of the static string data is at the start of the code section before the start label and with another version, I wrote the string data in a dead area at the end of the PE header. I used a dynamic jump table to get the actual code size down and it still stubornly sits at 6k finished.
For all of the effort and no size gain, an already difficult to read source became more or less unintelligible to anything else than an assembler so I gave up on the idea. After adding some additional functionality to it where it grew by 1 512 byte section, it was Pelle's linker that droped it back to 6k.
Sooner or later you get the idea that byte size reduction at a code level does not deliver the goods.
Already have that idea, so i gave up as well.. The only interesting thing in improving IMO is for speed when writing a routine which will be called a couple of million times. This is definitely worth improving, but since i can see no real use for it now i think i'll just still with the default linker options and with the normal coding style :wink