I'd like to create the smallest executable with the attached source.
If anybody has experimented combinations of assembler/linker to get
the smallest running executable, please give it a shoot, post your
complete command lines/batch files, and the executable and obj file
you get. Any combination of Masm/JWasm/Any compatible and Link/Polink...
that you are aware of and can create an exe file with the attached
source is welcome.
Thanks
Frank
These global variables produce very bloated code:
mov windowSize.Left, 0
mov windowSize.Right, 79
mov windowSize.Top, 0
mov windowSize.Bottom, 24
Make them local, or use a register to load them. Besides, m2m is often shorter than mov.
Quote from: jj2007 on January 17, 2013, 09:49:03 AM
These global variables produce very bloated code:
mov windowSize.Left, 0
mov windowSize.Right, 79
mov windowSize.Top, 0
mov windowSize.Bottom, 24
Make them local, or use a register to load them. Besides, m2m is often shorter than mov.
Thanks for the note Jochen. That's surely a way of sparing some bytes. :t
However I was asking about Assemblers/Linkers and their options to make an
executable program smaller compared to the same program assembled/linked
with different parameters and/or tools.
And an "exe compactor" could do the final job to get the smallest executable
program as the final touch.
deleted
Quote from: nidud on January 17, 2013, 10:29:45 AM
JWasm ascii.asm
JWlink format win pe file ascii.obj
12288 byte
upx ascii.exe
3072 byte
Hi nidud. I've tried using these instructions in a bat file:
\masm32\bin\JWASM.exe /c /coff /Cp /Zg /zlf /zls /nologo ASCII.asm
\masm32\bin\polink /SUBSYSTEM:CONSOLE /ALIGN:4096 ASCII.obj
and I get an executable file of 3072 bytes, as you did with your commands.
I'm wondering if a small file like this is compressable, considering the new
exe has to contain the decompressor code as well.
So I think upx is not useful in this case. Maybe a better combination of
parameters for Assembler/Linker could gain some bytes. ::)
mov windowSize.Left, 0
mov windowSize.Right, 79
mov windowSize.Top, 0
mov windowSize.Bottom, 24
mov bufferSize.x, 80
mov bufferSize.y, 25
mov startPoint.x, 0
mov startPoint.y, 0
nah - put them in initialized data
it takes more bytes of code to initialize them, whether it's local or global, than it does to stick them in
initialized data
the exception to that is startPoint
put that one in uninitialized data - it's initialized to 0 automatically :P
now - i know that's not what you were asking about - lol
if you use PoLink, you will get an EXE that is 512 bytes smaller
or, you can use ms Link, and combine sections like this
Link /SUBSYSTEM:CONSOLE /OPT:NOREF /MERGE:.data=.text /ALIGN:4 MyFile.obj
Quote from: frktons on January 17, 2013, 10:36:02 AM
Quote from: nidud on January 17, 2013, 10:29:45 AM
JWasm ascii.asm
JWlink format win pe file ascii.obj
12288 byte
upx ascii.exe
3072 byte
Hi nidud. I've tried using these instructions in a bat file:
\masm32\bin\JWASM.exe /c /coff /Cp /Zg /zlf /zls /nologo ASCII.asm
\masm32\bin\polink /SUBSYSTEM:CONSOLE /ALIGN:4096 ASCII.obj
and I get an executable file of 3072 bytes, as you did with your commands.
I'm wondering if a small file like this is compressable, considering the new
exe has to contain the decompressor code as well.
So I think upx is not useful in this case. Maybe a better combination of
parameters for Assembler/Linker could gain some bytes. ::)
Frank, have a look into \masm32\examples\exampl10\MemInfoMicro, there should be a batch file with commands to build that old version of this prog.
Also have a look into the BAT file used for building MemInfoMicro25 (http://masm32.com/board/index.php?topic=44.0). Take your notice on the /MERGE options, and, especially for an old linkers, /OPT:NOWIN98.
Using Polink with these options, I get an executable of 2,560 bytes :t
\masm32\bin\polink.exe /SUBSYSTEM:CONSOLE /MERGE:.data=.text /SECTION:.text,rwe "ascii.obj" > nul
Probably for this program only source code changes [as Dave and Jochen suggest] can spare some
more bytes.
deleted
Frank,
if you want to make it smaller, look at the code and data :P
a lot of times, looking at the disassembled code will bring out things you don't notice in the source
and - when you have related data - put them in a structure
then, instead of...
mov SomeData1,1
mov SomeData2,20
mov SomeData3,30
use
mov edx,offset SomeStruct
mov [edx].SOMESTRUCT.SomeData1,1
mov [edx].SOMESTRUCT.SomeData2,20
mov [edx].SOMESTRUCT.SomeData3,30
look at those 2 snippets in a disassembled listing :P
as Jochen mentioned, using m2m makes code smaller when the constants are small
push 20
pop [edx].SOMESTRUCT.SomeData2
that's because the immediate data (20) is stored in the code stream in a reduced form
whereas
mov [edx].SOMESTRUCT.SomeData2,20
the immediate data (20) is stored in the code stream as a dword (assuming SomeData2 is a dword)
however, push/pop is slower
it quite often doesn't matter when API calls are involved, anyway
Hi nidud.
About compressing the exe see my previous post.
Regarding the Text File Compressor and Scanner I'm collecting
the one thousand PROC I need, and the 10,000 necessary info.
The overall scheme is ready. Probably one of this ideas would
give the program the capability to compress a little even the
considered impossible to compress random files, it'd be a surprise
but I'm not sure for the time being it'll work as expected, after
all if it is considered an impossible task it has to mean something.
In few months I'll see and in case I'll show the results on the forum.
As they say the project is still work in progress, and all the
threads I started have something to do with it in a way or another.
I'm quite slow (http://masm32.com/board/index.php?action=dlattach;topic=1091.0;attach=926)
so don't expect fast results, and the project is quite complex to manage in Assembly
for a n00bist of my level :P
i should mention that talking about small code, we will get a message from Hutch - lol
be sure to use LODSB, STOSB, and LOOP, wherever possible :lol:
(http://img195.imageshack.us/img195/9819/crocodilesign.png)
Dave, your suggestions and Jochen's ones intrigue me. Considering you
have far more knowledge/experience than me I've to take these notes
in great consideration, so as time permits I'll try them and post the results.
QuoteLODSB, STOSB, and LOOP
whooooaaa, I've never used them, are they nice ones? :lol:
i use them all the time, where speed isn't critical - like parsing the command line or something
Hutch barks at me every time - but, he probably likes you more than me :lol:
Quote from: dedndave on January 17, 2013, 11:47:10 AM
i use them all the time, where speed isn't critical - like parsing the command line or something
Hutch barks at me every time - but, he probably likes you more than me :lol:
So they aren't fast, but I hope they are small at least :lol:
You know what they say, the more far away you are the more they like you :super-lol:
deleted
:biggrin:
> Hutch barks at me every time - but, he probably likes you more than me
Yeah yeah, teach people bad habits so they write garbage. :P (But HAY, it was really host stuff on an i386SX under MS-DOS)
Quote from: nidud on January 17, 2013, 12:10:02 PM
/MERGE:.data=.text
the AV scanners will love this one :lol:
QuoteRegarding the Text File Compressor and Scanner I'm collecting
the one thousand PROC I need,
hence the library then
Quote
if it is considered an impossible task it has to mean something
not impossible, but difficult -- if there is a will there is usually a way
Quotethe project is quite complex to manage in Assembly
true
QuoteI'm quite slow
perfection takes time :P
1] Yes
2] Yes
3] Yes
4] Yes
5] Yes
well I can say
I couldn't agree more :lol:
Well, I tried Dave's suggestion, but something went wrong.
.data
windowSize SMALL_RECT <0,79,0,24>
bufferSize COORD <80,25>
startPoint COORD <0,0>
so I got rid of these code:
mov windowSize.Left, 0
mov windowSize.Right, 79
mov windowSize.Top, 0
mov windowSize.Bottom, 24
mov bufferSize.x, 80
mov bufferSize.y, 25
mov startPoint.x, 0
mov startPoint.y, 0
But the console is displayed black, with nothing inside. :icon_rolleyes:
from the movie "Mission Impossible II"
QuoteThis isn't Mission Difficult, it's Mission Impossible. "Difficult" should be a walk in the park for you.
the order for SMALL_RECT members is Left, Top, Right, Bottom :P
windowSize SMALL_RECT <0,0,79,24>
put this one in uninitialized data - it will be filled with 0's
startPoint COORD <>
Quote from: dedndave on January 17, 2013, 12:51:56 PM
from the movie "Mission Impossible II"
QuoteThis isn't Mission Difficult, it's Mission Impossible. "Difficult" should be a walk in the park for you.
the order for SMALL_RECT members is Left, Top, Right, Bottom :P
windowSize SMALL_RECT <0,0,79,24>
put this one in uninitialized data - it will be filled with 0's
startPoint COORD <>
I suspected it, about the walk in the park I mean :lol:
Yes Master Dave, that's the correct order. Anyway, and I suspected it
as well, no gain at all in the exe size: still 2,560 bytes.
But at least it works again :P
well - each section is allocated in 512 byte chunks, as i recall
so, you have to get down to the next 512-byte step to notice an improvement
that line was from the character played by Anthony Hopkins
it wasn't the greatest movie, but he's always good
not as great of an actor as everyone may say - he's a bit one-dimensional, actually
i still like him
he made a good Hannibal - lol
Quote from: dedndave on January 17, 2013, 01:13:14 PM
well - you each section is allocated in 512 byte chunks, as i recall
so, you have to get down to the next 512-byte step to notice an improvement
that line was from the character played by Anthony Hopkins
it wasn't the greatest movie, but he's always good
not as great of an actor as everyone may say - he's a bit one-dimensional, actually
i still like him
he made a good Hannibal - lol
That was my suspect ;)
I like Anthony Hopkins as well, a nice English styled actor :t
and yes He is
a bit one-dimensional
.data?
windowSize SMALL_RECT <>
windowRSize RECT <>
.code
mov windowSize.Left, 127 ; 9
m2m windowSize.Left, 127 ; 11
add windowSize.Left, 127 ; 8
mov windowRSize.left, 127 ; 10
m2m windowRSize.left, 127 ; 8
add windowRSize.left, 127 ; 7
;)
.data
windowSize SMALL_RECT <0,0,79,24> ;8
bufferSize COORD <80,25> ;4
total clock cycles = 0
;)
Quote from: dedndave on January 17, 2013, 05:32:10 PM
.data
windowSize SMALL_RECT <0,0,79,24> ;8
bufferSize COORD <80,25> ;4
total clock cycles = 0
;)
If they don't change then put them in .code
Of course, some APIs will expect to write to it...
Quote from: jj2007 on January 17, 2013, 05:17:23 PM
.data?
windowSize SMALL_RECT <>
windowRSize RECT <>
.code
mov windowSize.Left, 127 ; 9
m2m windowSize.Left, 127 ; 11
add windowSize.Left, 127 ; 8
mov windowRSize.left, 127 ; 10
m2m windowRSize.left, 127 ; 8
add windowRSize.left, 127 ; 7
;)
Thanks Jochen, good to know :t
Quote from: dedndave on January 17, 2013, 05:32:10 PM
.data
windowSize SMALL_RECT <0,0,79,24> ;8
bufferSize COORD <80,25> ;4
total clock cycles = 0
;)
Yes Dave, the most compact and fast should be like that. :biggrin:
Quote from: sinsi on January 17, 2013, 05:52:27 PM
If they don't change then put them in .code
Of course, some APIs will expect to write to it...
Don't understand why to put them in .code. ::)
if you merge sections at link-time, the advantage of putting it in the code section is gone
but, the idea is to reduce one section so that the 512-byte step is met
if you spend time on the code, you can probably get the EXE down to 1.5 kb :P
almost everything you had in the .DATA section (except for the string) could be an EQUate
.data
ConTitle db " ----------- ** Extended ASCII chart displayable characters ** ----------", 0
PtrConTitle DWORD ConTitle + 17 ; Points to " Extended..." part of ConTitle
NewProcSize DWORD FromPoint - ToPoint
inpbyte DWORD 1
;----------------------------------------------------------------------
; ASCII chars to draw a simple box
;----------------------------------------------------------------------
TopLeft db 218
TopRight db 191
BottomLeft db 192
BottomRight db 217
HorizLine db 196
VerticLine db 179
;----------------------------------------------------------------------
Unit BYTE One
Ten BYTE Space
Hundred BYTE Space
EndOfTask BYTE 0
AsciiCode DWORD 205F2000H ; 4 bytes = 1 CHAR_INFO
; char 1 White on Magenta Attribute
your string is not modified, as it exists in .DATA
so, you could take sinsi's suggestion....
put the string and the structures we mentioned in the .CODE section
that would eliminate the .DATA section, altogether
you cannot modify data that you place in the .CODE section
at least, not without changing the section attribute - probably not a good practice
the .DATA? section consumes no space in the EXE, other than the entries to create the section :P
after that, there are several little things, here and there
look at the disassembled code to see how many bytes things use
lea eax, ConsoleScreen
add eax, TitleStartPoint
mov eax,offset ConsoleScreen+TitleStartPoint
We are moving aside and far away from my first intention,
that was to know something about switches and parameters
used by assemblers/linkers to reduce the size of an executable.
When I created this small program a couple of years ago, it was
a challenge to reduce 12k size of a prog and its file, to something
less, and the result was a prog that can be assembled and linked
in 2.5K, which means about 80% less than the original.
But we are now in the compressor time so let's move forward and see
if we can shrink it from 2.5K to 2K or less.
Another nice deviation that stays inside the "compressing matter"
anyway. :lol:
still, these should be made into EQUates - no need for all that data
PtrConTitle DWORD ConTitle + 17 ; Points to " Extended..." part of ConTitle
NewProcSize DWORD FromPoint - ToPoint
inpbyte DWORD 1
;----------------------------------------------------------------------
; ASCII chars to draw a simple box
;----------------------------------------------------------------------
TopLeft db 218
TopRight db 191
BottomLeft db 192
BottomRight db 217
HorizLine db 196
VerticLine db 179
;----------------------------------------------------------------------
Unit BYTE One
Ten BYTE Space
Hundred BYTE Space
EndOfTask BYTE 0
AsciiCode DWORD 205F2000H ; 4 bytes = 1 CHAR_INFO
; char 1 White on Magenta Attribute
the first one, you have already done - you can probably get rid of it
it's also likely to reduce the code size
mov al,TopLeft
mov [edx],al
as an EQUate...
mov byte ptr [edx],TopLeft
Creating small executables is interesting also while working with HLLs.
Quote from: Vortex on January 18, 2013, 06:14:16 AM
Creating small executables is interesting also while working with HLLs.
But the EXE files generated by compilers are not so small.
Gunther
Quote from: Gunther on January 18, 2013, 07:36:05 AM
But the EXE files generated by compilers are not so small.
Erol is a genius, he can produce a 1.5k C executable. The problem with such tiny programs is that a) they can't fill a hard drive sector (4k) and b) they don't do anything useful (but wait until Alex logs in :lol:)
I've done some refinement to the code, and got rid of about
20 instructions, sparing some 50-60 bytes, but still not sufficient
to reduce the size to 2K. It's actually fixed at 2,5K.
I've seen that there is a lot of space for size reduction, so the 2K
goal is quite feasible.
Attached the shrinked version 0.4.
Frank
In order to get rid of the .data section altogether, I need
to transform this line of .data:
ConTitle db " ----------- ** Extended ASCII chart displayable characters ** ----------", 0
in a line of LOCAL to put inside the PROC that uses it.
I have no clue how to do it. Any help is welcome.
it doesn't need to be local
what you want is to put it in the code section
if you did want it to be local, you could push it onto the stack in reverse order - very clumsy
Quote from: dedndave on January 18, 2013, 05:01:21 PM
it doesn't need to be local
what you want is to put it in the code section
if you did want it to be local, you could push it onto the stack in reverse order - very clumsy
I want to put it in the .code section, but I don't know how.
How I define it, where I put these bytes?
stick it any place you like, really - someplace where it won't be executed :P
DisplaySequence ENDP
ConTitle db " ----------- ** Extended ASCII chart displayable characters ** ----------", 0
; -------------------------------------------------------------------------
; Writes the Screen Title with enhanced color attribute White on Magenta
;--------------------------------------------------------------------------
WriteScreenTitle PROC
as a matter of practice, i try to define things earlier in the source than where i use them
that isn't always practical
Quote from: dedndave on January 18, 2013, 05:18:22 PM
stick it any place you like, really - someplace where it won't be executed :P
DisplaySequence ENDP
ConTitle db " ----------- ** Extended ASCII chart displayable characters ** ----------", 0
; -------------------------------------------------------------------------
; Writes the Screen Title with enhanced color attribute White on Magenta
;--------------------------------------------------------------------------
WriteScreenTitle PROC
as a matter of practice, i try to define things earlier in the source than where i use them
that isn't always practical
In this way the .data section is not created? Because this is my goal here.
if there is nothing left in the .DATA section, don't use .DATA and it won't be created
Quote from: dedndave on January 18, 2013, 05:24:53 PM
if there is nothing left in the .DATA section, don't use .DATA and it won't be created
OK, good. :t My .data section is empty and deleted from the program,
but nothing changes in the size of the prog. 2,560 bytes ::)
The prog without the .data section attached. Anyone can see where I can
save some other bytes?
DisplayFmt PROC szFmtName:DWORD
LOCAL rc:SMALL_RECT
movlps xmm0, windowSize ; make a copy
movlps rc, xmm0
INVOKE WriteConsoleOutput, wHnd, szFmtName, DWORD PTR bufferSize,
DWORD PTR startPoint, addr rc ; offset windowSize crashes the app
ret
DisplayFmt ENDP
Quote from: sinsi on January 17, 2013, 05:52:27 PM
If they don't change then put them in .code
Of course, some APIs will expect to write to it...
Quote from: jj2007 on January 18, 2013, 08:03:05 PMoffset windowSize crashes the app
Quote from: MSDNlpWriteRegion [in, out]
A pointer to a SMALL_RECT structure. On input, the structure members specify the upper-left and lower-right coordinates of the console screen buffer rectangle to write to. On output, the structure members specify the actual rectangle that was used.
Quote from: sinsi on January 18, 2013, 09:15:50 PMOn output,
Indeed, see movlps above. Strange that it apparently did not crash on Frank's machine.
Does the attached 2K version crashes as well? On my pc is works.
If it does, I'll follow Jochen's advice and create a LOCAL variable.
I don't think it will affect the 2.048 bytes result.
To get there I had to leave only the essential and get rid of some
redundancy here and there.
And, well I restored the .data section as well, the link parameters I'm
using already merge data section so there is no need to make
strange things with preinitialized data.
2k, no crash :t
push 18004Fh ;79 x 24
push 0
INVOKE SetConsoleWindowInfo, wHnd, TRUE, esp
pop ecx
pop edx
:P
Initialised local variables? You are cheating, Dave ;-)
Quote from: jj2007 on January 19, 2013, 01:50:18 AM
2k, no crash :t
I think it is enough, getting rid of 512 bytes more would be a bit complex
and too long way. ;)
Quote from: dedndave on January 19, 2013, 01:50:56 AM
push 18004Fh ;79 x 24
push 0
INVOKE SetConsoleWindowInfo, wHnd, TRUE, esp
pop ecx
pop edx
:P
Is this the equivalent of:
windowSize SMALL_RECT <N0,N0,N79,N24>
INVOKE SetConsoleWindowInfo, wHnd, TRUE, ADDR windowSize
?
You have pushed 8 bytes on the stack,
The SMALL_RECT is 8 bytes long.
Nice little trick to get around things.
Is it smaller or just smarter than usual code?
when you push a constant, the assembler assumes it's a dword in a use32 segment
so, you have created the structure, temporarily, on the stack
when you are done using it, pop, pop, it's gone
one thing that is convenient, in this case, is that a pointer to the structure is in ESP
because the structure pointer is the last parameter of the function, you can use it directly
if the function had other parms afterwards, you'd have to move the current stack pointer into a register
ReadFile and WriteFile are examples of this if you want to create a temporary nNumberOfBytes dword
push 0
mov edx,esp
INVOKE ReadFile,hFile,lpFileBuf,uFileSize,edx,NULL
pop ecx
that's because parameters are pushed onto the stack in reverse order
so - when NULL is pushed, ESP changes
Quote from: dedndave on January 19, 2013, 02:27:24 AM
when you push a constant, the assembler assumes it's a dword in a use32 segment
so, you have created the structure, temporarily, on the stack
when you are done using it, pop, pop, it's gone
one thing that is convenient, in this case, is that a pointer to the structure is in ESP
because the structure pointer is the last parameter of the function, you can use it directly
if the function had other parms afterwards, you'd have to move the current stack pointer into a register
ReadFile and WriteFile are examples of this if you want to create a temporary nNumberOfBytes dword
push 0
mov edx,esp
INVOKE ReadFile,hFile,lpFileBuf,uFileSize,edx,NULL
pop ecx
that's because parameters are pushed onto the stack in reverse order
so - when NULL is pushed, ESP changes
Thanks Master Dave, and here it is a present for you,
the 1.5K version of the program :P
Do you think I've to shrink it more or I can pass through and
move to something else? :lol:
1.5 kb is about as small as a PE EXE gets
Alex can make a smaller EXE, but he plays a lot of tricks to do it :P
That impressive and something I have needed.
Andy
Quote from: Magnum on January 19, 2013, 03:32:24 AM
That impressive and something I have needed.
Andy
I'm happy to be of some help. :t
:biggrin:
> 1.5 kb is about as small as a PE EXE gets
masm1k.exe is 1024 bytes. exampl07 directory. Done years ago.
Quote from: hutch-- on January 19, 2013, 08:03:53 AM
:biggrin:
> 1.5 kb is about as small as a PE EXE gets
masm1k.exe is 1024 bytes. exampl07 directory. Done years ago.
If the program only opens an empy window maybe it is possible
to do it in 700-800 bytes more or less, but it will appear as 1,024
anyway. I challenged everybody 2 years ago to shrink a 12K exe+
screen, but there was no real competition. I built it, step by
step, and here it is now. Somebody thought it was more or less
an impossible task. And I tend to love impossible tasks by my own
nature. :lol:
http://www.phreedom.org/research/tinype/ (http://www.phreedom.org/research/tinype/)
Used to be able to write com files in a few bytes way back in the day. I think 5 bytes for a reboot code.
If they haven't changed the spec, the link above is the tiniest I know about.
Quote from: npnw on January 20, 2013, 09:41:10 PM
http://www.phreedom.org/research/tinype/ (http://www.phreedom.org/research/tinype/)
Used to be able to write com files in a few bytes way back in the day. I think 5 bytes for a reboot code.
If they haven't changed the spec, the link above is the tiniest I know about.
Hi npnw,
I wonder how the author of that article managed to link the object module :
link /nologo /ENTRY:main /NODEFAULTLIB /SUBSYSTEM:WINDOWS /ALIGN:1 tiny.obj
The alignment value 1 is less than section alignment 16. Some version(s) of Windows will refuse to run very small portable executables.
:biggrin:
You can do a "REBOOT.COM" in 2 bytes, "int 19h". :P
Erol is correct here, go below 512 byte alignment and it becomes unreliable, particularly on earlier versions of Win32. The linkers generate the warning for good reason, it does not comply with the PE specs for Win32.
Quote from: hutch-- on January 20, 2013, 11:16:36 PM
:biggrin:
You can do a "REBOOT.COM" in 2 bytes, "int 19h". :P
:lol: :lol: :lol:
frktons,
yup, that was what I was thinking!
Vortex,
I read a PE format code for NT 3.1 in another article, and I think he referenced it in his article that there were windows versions that wouldn't run that small of program. However, most will run it fine.
If Dave can cheat, well Ich ....
; com.asm Com file template
;
; Ahh....Back in time when things were simpler, No I-Phones, Gas Wars were common, and
folks said Please and Thank you.
;
;
.model tiny
.386
.code
org 100h
begin:
jmp start
; data goes here
start:
int 20h ; proper exit
end begin
this is me, cheating :P
.MODEL Tiny
.386
OPTION CaseMap:None
;####################################################################################
.CODE
;************************************************************************************
ORG 100h
_main PROC NEAR
ret
_main ENDP
;####################################################################################
END _main
Quote from: dedndave on January 22, 2013, 03:19:14 AM
.MODEL Tiny
.386
OPTION CaseMap:None
;####################################################################################
.CODE
;************************************************************************************
ORG 100h
_main PROC NEAR
ret
_main ENDP
;####################################################################################
END _main
Dave won the prize with his "Do nothing" program :greenclp: :eusa_dance: :greenclp:
.COM programs start out with a 0 word pushed onto the stack and CS = DS = ES = SS = PSP
at PSP:0000, you will find CD 20, which is INT 20h
so, a NEAR RET gets you a terminate :P
MZ .EXE's start out a little differently
the code segment is not the same as the PSP segment, like .COM's
as i recall, DS and ES are pointing to the PSP, though
so, you can do this...
xor ax,ax
push ds
push ax
;
;
;
retf
the 8086/8088 didn't support pushing constants, so you couldn't use PUSH 0
most of the general registers are set to 0, i think
you might get away with PUSH DX or something
AX may not be 0 if there is 1 or 2 valid parsed path(s) on the command line
push ds
push dx
;
;
;
retf
i think that's the minimal MZ EXE - 3 bytes of code, 512 for the header
you're not supposed to use INT 20h from an EXE, unless you set cs to psp - something like that
If just opening and closing meets the requirements, then I think you can get the same apparent result by renaming an arbitrary 1-byte file to whatever.exe.
that would be cheating :lol:
i wonder how big an exe would be if we used one of these...
http://www.linurs.org/mc14500.html (http://www.linurs.org/mc14500.html)
:biggrin:
Hi,
This also works. And is small. Doesn't do much though.
Has to be a *.COM program of course.
CODE SEGMENT
ASSUME CS:CODE,DS:CODE,ES:NOTHING
ORG 100H ; COM file opening
START:
RET ; Ensure near return.
CODE ENDS
END START
Cheers,
Steve N.
Hi npnw,
The article was interesting because MS link will simply refuse to link the object files because of the improper alignment value 1. At least, this is what I observed with the linker supplied with the Masm32 package. Windows 2000 will not run executables not importing API functions.
WTF are you guys smoking ... ? :shock: :lol: :t
Vortex,
He made reference to the API in win 2000 in the article. The linker probably won't work because of the 16 byte limit, or derivative of 16 for byte alignment and memory transfers at that time. Otherwise it would take two or more memory reads to transfer with the processor. I'm not sure if they have made this 32 bit now, or 64 byte alignment to optimize memory access.
Otherwise the 1 byte would work for 8088 virtual mode. If they have decoupled the linker from hardware, you can do this. If they are optimized for the hardware, this is why it wouldn't work.
http://msdn.microsoft.com/en-us/library/s0ksfwcf(v=vs.80).aspx (http://msdn.microsoft.com/en-us/library/s0ksfwcf(v=vs.80).aspx)
Align
http://msdn.microsoft.com/en-us/library/dwa9fwef(v=vs.80).aspx (http://msdn.microsoft.com/en-us/library/dwa9fwef(v=vs.80).aspx)
directive references
http://msdn.microsoft.com/en-US/library/8t163bt0(v=vs.80).aspx (http://msdn.microsoft.com/en-US/library/8t163bt0(v=vs.80).aspx)
These were from the visual studio 2005 there are links to other assembler versions.
Quote from: npnw on January 22, 2013, 09:22:23 AM
He made reference to the API in win 2000 in the article.
Here is the problem. Windows 2000 will simply refuse to run a PE not importing an API function. ( tiny.exe - 97 bytes )
Tried the 97 bytes example on a virtual Windows 2000 running on qemu. Ollydbg reported : Bad or unknown format of 32-bit executable file 'C:\tiny.exe'
http://www.masmforum.com/board/index.php?topic=10252.msg125601#msg125601 :biggrin:
Hi Alex,
Quote from: Antariy on January 23, 2013, 08:32:50 AM
http://www.masmforum.com/board/index.php?topic=10252.msg125601#msg125601 :biggrin:
not bad, Alex, not bad.
Gunther
Quote from: Antariy on January 23, 2013, 08:32:50 AM
http://www.masmforum.com/board/index.php?topic=10252.msg125601#msg125601 :biggrin:
It doesn't seem to work on win7/64 bit system though.
it's a 16-bit program, which isn't supported in 64-bit windows OS's
i think it can be done using DosBox or something
Quote from: dedndave on January 24, 2013, 09:23:17 PM
it's a 16-bit program, which isn't supported in 64-bit windows OS's
i think it can be done using DosBox or something
I think it's time to look forward. 16 bit world was funny, but only because we were young.
Thinking about all the limitations it had, it's much better to live in a 32/64 bit modern version.
:P
Frank,
Quote from: frktons on January 25, 2013, 12:36:47 PM
I think it's time to look forward. 16 bit world was funny, but only because we were young.
Thinking about all the limitations it had, it's much better to live in a 32/64 bit modern version.
:P
wise spoken, but we shouldn't forget some good tricks from the old 8 and 16 bit world.
Gunther
Quote from: Gunther on January 26, 2013, 06:34:06 AM
Frank,
wise spoken, but we shouldn't forget some good tricks from the old 8 and 16 bit world.
Gunther
Agreed. :t
I agree with you.
We can just look at the code in some of our 32 bit programs.
; Fireworks - with MMX blur and light effects
; by ronybc from Kerala,INDIA
; website: http://www.ronybc.8k.com
.686p
.MMX
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
; struct spark {float x,xv,y,yv;};
; struct FireShell {DWORD life; float air; spark d[250];};
; sizeof FireShell = 250*4*4+8 = 4008 bytes
EXX EQU 4
EXY EQU 8
AIR EQU 12
SPARC EQU 16
.data
ClassName db "apocalypse",0
AppName db "Fireworks MMX ...by ronybc",0,0,0,0,0,0
info db "Fireworks Version: 3.40229 - Freeware",13,10
db 13,10
db "WARNING: This is a Fireware, softwares that push CPU temperature",13,10
db "to its maximum. It does No harm, but overclockers better stay away :)",13,10
db "Entire source code of this program is free available at my website. ",13,10
db 13,10
db "If you like the work, help the author with donations.",13,10
db "see http://www.ronybc.8k.com/support.htm",13,10
db 13,10
db "SPACE & ENTER keys toggles 'Gravity and Air' and",13,10
db "'Light and Smoke' effects respectively.",13,10
db "And clicks explode..! close clicks produce more light",13,10
db 13,10
db "Manufactured, bottled and distributed by",13,10
db "Silicon Fumes Digital Distilleries, Kerala, INDIA",13,10
db 13,10
db "Copyright 1999-2004 © Rony B Chandran. All Rights Reserved",13,10
db 13,10
db "This isn't the Final Version",13,10
db "check http://www.ronybc.8k.com for updates and more",0
seed dd 2037280626
wwidth dd 680 ; 1:1.618, The ratio of beauty ;)
wheight dd 420 ; smaller the window faster the fires
maxx dd 123 ; 123: values set on execution
maxy dd 123 ; this thing is best for comparing
lightx dd 123 ; cpu performance.
lighty dd 123
flash dd 123
flfactor dd 0.92
adg dd 0.00024 ; 0.00096 acceleration due to gravity
xcut dd 0.00064
nb dd 5 ; number of shells
nd dd 400 ; sparks per shell
sb dd 0 ; value set on execution
maxpower dd 5
minlife dd 500 ; altered @WndProc:WM_COMMAND:1300
motionQ dd 16 ; 01-25, altered @WndProc:WM_COMMAND:1210
fcount dd 0
GMode dd 1 ; atmosphere or outer-space
CMode dd 0 ; color shifter
EMode dd 1 ; special effects
click dd 0
stop dd 0
fadelvl dd 1
chemtable dd 00e0a0ffh, 00f08030h, 00e6c080h, 0040b070h, 00aad580h
bminf BITMAPINFO <<40,0,0,1,24,0,0,0,0,0,0>>
.data?
hInstance HINSTANCE ?
hwnd LPVOID ?
hmnu HWND ?
wnddc HDC ?
hFThread HANDLE ?
hHeap HANDLE ?
idThread1 DWORD ?
idThread2 DWORD ?
bitmap1 LPVOID ?
bitmap2 LPVOID ?
hFShells LPVOID ?
msg MSG <>
wc WNDCLASSEX <>
.code
random PROC base:DWORD ; Park Miller random number algorithm
mov eax, seed ; from M32lib/nrand.asm
xor edx, edx
mov ecx, 127773
div ecx
mov ecx, eax
mov eax, 16807
mul edx
mov edx, ecx
mov ecx, eax
mov eax, 2836
mul edx
sub ecx, eax
xor edx, edx
mov eax, ecx
mov seed, ecx
div base
mov eax, edx
ret
random ENDP
; -------------------------------------------------------------------------
Light_Flash3 PROC x1:DWORD, y1:DWORD, lum:DWORD, src:DWORD, des:DWORD
LOCAL mx:DWORD, my:DWORD, x2:DWORD, y2:DWORD, tff:DWORD
mov eax,lum
shr eax,1 ; Light_Flash: dynamic 2D lighting routine
mov lum,eax ; does not uses any pre-computed data
mov tff,255 ; ie. pure light frum tha melting cpu core :)
mov eax,maxx
mov mx,eax
mov eax,maxy
dec eax
mov my,eax
mov esi,src
mov edi,des
xor eax,eax
mov y2,eax
ylp3: ; 2x2 instead of per pixel lighting
xor eax,eax ; half the quality, but higher speed
mov x2,eax
xlp3:
mov eax,y2
sub eax,y1
imul eax
mov ebx,x2
sub ebx,x1
imul ebx,ebx
add eax,ebx
mov edx,lum
imul edx,edx
xor ebx,ebx
cmp eax,edx
ja @F ; jump to end causes time waves
push eax
fild dword ptr[esp]
fsqrt
fidiv lum ; this code is -nonlinear-
fld1
fsubrp st(1),st(0)
fmul st(0),st(0) ; curve
fmul st(0),st(0) ; curve more
fimul tff
fistp dword ptr[esp]
pop ebx
imul ebx,01010101h
@@:
mov eax,y2
imul maxx
add eax,x2
lea eax,[eax+eax*2]
mov edx,maxx
lea edx,[edx+edx*2]
add edx,eax
movd MM2,ebx ; simply add with saturation
movq MM0,[esi+eax] ; gamma correction is against this code
psllq MM2,32
movq MM1,[esi+edx]
movd MM3,ebx
por MM2,MM3
paddusb MM0,MM2
movd [edi+eax],MM0
paddusb MM1,MM2
psrlq MM0,32
movd [edi+edx],MM1
movd ebx,MM0
psrlq MM1,32
mov [edi+eax+4],bx
movd ecx,MM1
mov [edi+edx+4],cx
emms
@@:
mov eax,x2
add eax,2
mov x2,eax
cmp eax,mx
jbe xlp3
mov eax,y2
add eax,2
mov y2,eax
cmp eax,my
jbe ylp3
ret
Light_Flash3 ENDP
; -------------------------------------------------------------------------
Blur_MMX2 PROC ; 24bit color version
mov edi,bitmap2 ; (Developed under an old SiS6326 graphic card
mov esi,bitmap1 ; which prefers 24bit for faster operation)
mov bitmap1,edi ; Note: SiS315 is excellent, good rendering quality
mov bitmap2,esi
pxor MM7,MM7
mov eax,fadelvl
imul eax,00010001h
mov [ebp-4],eax
mov [ebp-8],eax
movq MM6,[ebp-8]
mov eax,maxx
lea eax,[eax+eax*2]
mov ebx,eax
imul maxy
push eax ; maxy*maxx*3
lea edx,[ebx-3]
lea ebx,[ebx+3]
neg edx
xor eax,eax
lea esi,[esi-3]
@@:
movd MM0,[esi] ; code enlarged version
punpcklbw MM0,MM7 ; optimized for speed, not size
movd MM1,[esi+8]
movd MM2,[esi+16]
punpcklbw MM1,MM7
punpcklbw MM2,MM7
movd MM3,[esi+6]
movd MM4,[esi+14]
movd MM5,[esi+22]
punpcklbw MM3,MM7
paddw MM0,MM3
punpcklbw MM4,MM7
paddw MM1,MM4
punpcklbw MM5,MM7
paddw MM2,MM5
movd MM3,[esi+ebx]
punpcklbw MM3,MM7
paddw MM0,MM3
movd MM4,[esi+ebx+8]
movd MM5,[esi+ebx+16]
punpcklbw MM4,MM7
paddw MM1,MM4
punpcklbw MM5,MM7
paddw MM2,MM5
movd MM3,[esi+edx]
punpcklbw MM3,MM7
paddw MM0,MM3
movd MM4,[esi+edx+8]
movd MM5,[esi+edx+16]
punpcklbw MM4,MM7
paddw MM1,MM4
punpcklbw MM5,MM7
paddw MM2,MM5
psrlw MM0,2 ; neibours only, ie. smoky blur
psrlw MM1,2
psrlw MM2,2
psubusw MM0,MM6 ; fade
psubusw MM1,MM6
psubusw MM2,MM6
packuswb MM0,MM7
lea esi,[esi+12]
packuswb MM1,MM7
packuswb MM2,MM7
movd [edi+eax],MM0
movd [edi+eax+8],MM1
movd [edi+eax+16],MM2
lea eax,[eax+12]
cmp eax,[esp]
jbe @B
pop eax
emms ; free fpu registers for following
ret ; floating-point functions
Blur_MMX2 ENDP
; -------------------------------------------------------------------------
FShell_explodeOS PROC hb:DWORD
mov edi,hb
add edi,SPARC
mov eax,nd
dec eax
shl eax,4
@@:
fld dword ptr[edi+eax] ; x coordinate
fadd dword ptr[edi+eax+4] ; x velocity
fstp dword ptr[edi+eax]
fld dword ptr[edi+eax+8] ; y coordinate
fadd dword ptr[edi+eax+12] ; y velocity
fstp dword ptr[edi+eax+8]
sub eax,16
jnc @B
dec dword ptr[edi-SPARC]
mov eax,[edi-SPARC] ; return(--life)
ret
FShell_explodeOS ENDP
; -------------------------------------------------------------------------
FShell_explodeAG PROC hb:DWORD
mov edi,hb
fld adg ; acceleration due to gravity
fld dword ptr[edi+AIR] ; air resistance
add edi,SPARC
mov eax,nd
dec eax
shl eax,4
@@:
fld dword ptr[edi+eax+4] ; x velocity
fmul st(0),st(1) ; deceleration by air
fst dword ptr[edi+eax+4]
fadd dword ptr[edi+eax] ; x coordinate
fstp dword ptr[edi+eax]
fld dword ptr[edi+eax+12] ; y velocity
fmul st(0),st(1) ; deceleration by air
fadd st(0),st(2) ; gravity
fst dword ptr[edi+eax+12]
fadd dword ptr[edi+eax+8] ; y coordinate
fstp dword ptr[edi+eax+8]
sub eax,16
jnc @B
fcompp ; marks st(0) and st(1) empty
dec dword ptr[edi-SPARC]
mov eax,[edi-SPARC] ; return(--life)
ret
FShell_explodeAG ENDP
; -------------------------------------------------------------------------
FShell_render PROC hb:DWORD, color:DWORD
LOCAL expx:DWORD, expy:DWORD
mov edi,hb
mov eax,[edi+EXX]
mov expx,eax
mov eax,[edi+EXY]
mov expy,eax
add edi,SPARC
mov ebx,color
dec ebx
;and ebx,3
mov ecx,offset chemtable
mov edx,hFShells ; floats are beautiful, and cheap source of
add edx,32 ; the chemical used for multi colored fires
mov eax,CMode
or eax,eax
cmovz edx,ecx
mov edx,[edx+ebx*4]
mov ecx,nd
dec ecx
shl ecx,4
mov esi,bitmap1
push maxy ; using stack adds speed
push maxx ; (local variables)
push edx
@@:
fld dword ptr[edi+ecx+4]
fabs
fld xcut ; low cost code for independant burnouts
fcomip st(0),st(1)
fistp dword ptr[esp-4]
jae forget
fld dword ptr[edi+ecx]
fistp dword ptr[esp-4]
fld dword ptr[edi+ecx+8]
fistp dword ptr[esp-8]
mov eax,[esp-8]
cmp eax,[esp+8]
jae forget
mov ebx,[esp-4]
cmp ebx,[esp+4]
jae forget
imul dword ptr[esp+4]
add eax,ebx
lea eax,[eax+eax*2]
mov edx,[esp]
mov [esi+eax],dx
shr edx,16
mov [esi+eax+2],dl
forget:
sub ecx,16
jnc @B
;add esp,12 'leave'ing (ENDP)
ret
FShell_render ENDP
; -------------------------------------------------------------------------
FShell_recycle PROC hb:DWORD, x:DWORD, y:DWORD
mov edi,hb
mov eax,x
mov [edi+EXX],eax
mov eax,y
mov [edi+EXY],eax
mov eax,x
mov lightx,eax ; Light last one
mov eax,y
mov lighty,eax
mov eax,flash ; having only one light source
add eax,3200 ; 3200 million jouls...!
mov flash,eax ; add if previous lighting not extinguished
invoke random,20
inc eax
imul minlife
mov ebx,eax ; sync explosions by mouse clicks with rest
mov eax,[edi] ; by maintaining minimum delay of 'minlife'
xor edx,edx
idiv minlife
add edx,ebx
mov [edi],edx
invoke random,30 ; like its real world counterpart, creation process
add eax,10 ; is long and boring but the end product is explodin..
mov [esp-4],eax ; refer C++ source also. Most of the below area
mov eax,10000 ; is blind translation of that original C code
mov [esp-8],eax ; i crawled on that code as a Human C compiler...!
fld1
fild dword ptr[esp-4]
fidiv dword ptr[esp-8]
fsubp st(1),st(0)
fstp dword ptr[edi+AIR]
add edi,SPARC
fild y
fild x
mov eax,1000
mov [esp-4],eax
fild dword ptr[esp-4] ; 1000 (constant)
invoke random,maxpower
inc eax
mov [esp-4],eax
fild dword ptr[esp-4] ; power
mov ecx,nd
dec ecx
shl ecx,4
@@:
push ecx
invoke random,2000
mov [esp-4],eax
fild dword ptr[esp-4]
fsub st(0),st(2)
fdiv st(0),st(2)
fmul st(0),st(1)
mov ecx,[esp]
fstp dword ptr[edi+ecx+4]
fld st(0)
fmul st(0),st(0)
fld dword ptr[edi+ecx+4]
fmul st(0),st(0)
fsubp st(1),st(0)
fsqrt
invoke random,2000
mov [esp-4],eax
fild dword ptr[esp-4]
fsub st(0),st(3)
fdiv st(0),st(3)
fmulp st(1),st(0)
mov ecx,[esp]
fstp dword ptr[edi+ecx+12]
fld st(2)
fstp dword ptr[edi+ecx]
fld st(3)
fstp dword ptr[edi+ecx+8]
pop ecx
sub ecx,16
jnc @B
fcompp
fcompp
ret
FShell_recycle ENDP
; -------------------------------------------------------------------------
FireThread:
invoke SetThreadPriority,idThread1,THREAD_PRIORITY_HIGHEST
invoke GetDC,hwnd
mov wnddc,eax
invoke GetProcessHeap
mov hHeap,eax
invoke HeapAlloc,hHeap,HEAP_ZERO_MEMORY,4194304
add eax,4096 ; blur: -1'th line problem
mov bitmap1,eax
invoke HeapAlloc,hHeap,HEAP_ZERO_MEMORY,4194304
add eax,4096 ; blur: -1'th line problem
mov bitmap2,eax
mov eax,nd
shl eax,4
add eax,SPARC
mov sb,eax ; size of FShell = nd*16+8
imul nb ; array size = nb*sb
invoke HeapAlloc,hHeap,HEAP_ZERO_MEMORY,eax
mov hFShells,eax
finit ; initialise floating point unit
mov ax,07fh ; low precision floats
mov word ptr[esp-4],ax ; fireworks... not space rockets
fldcw word ptr[esp-4]
sub ebp,12 ; as 3 local variables
mov eax,nb
mov [ebp],eax
mov eax,hFShells
mov [ebp+4],eax
initshells:
;mov eax,maxx ; naah... not needed
;shr eax,1 ; trusting auto-zero
;invoke FShell_recycle,[ebp+4],eax,maxy
;mov eax,sb
;add [ebp+4],eax
;dec dword ptr[ebp]
;jnz initFShells
;mov flash,6400
lp1:
mov eax,motionQ
mov dword ptr[ebp+8],eax
lp2:
mov eax,nb
mov [ebp],eax
mov eax,hFShells
mov [ebp+4],eax
lp3:
invoke FShell_render,[ebp+4],[ebp]
mov eax,GMode
mov ecx,offset FShell_explodeAG
mov ebx,offset FShell_explodeOS
test eax,eax
cmovz ecx,ebx
push [ebp+4]
call ecx
test eax,eax
jns @F
invoke random,maxy
push eax
mov eax,maxx
add eax,eax
invoke random,eax
mov edx,maxx
shr edx,1
sub eax,edx
push eax
push [ebp+4]
call FShell_recycle
@@:
mov eax,sb
add [ebp+4],eax
dec dword ptr[ebp]
jnz lp3
dec dword ptr[ebp+8]
jnz lp2
mov eax,EMode
test eax,eax
jz r1
mov eax,CMode ; switch pre/post blur according to -
test eax,eax ; current chemical in fire
jz @F
invoke Blur_MMX2
@@:
invoke Light_Flash3,lightx,lighty,flash,bitmap1,bitmap2
invoke SetDIBitsToDevice,wnddc,0,0,maxx,maxy,\
0,0,0,maxy,bitmap2,ADDR bminf,DIB_RGB_COLORS
mov eax,CMode
test eax,eax
jnz r2
invoke Blur_MMX2
jmp r2
r1:
invoke SetDIBitsToDevice,wnddc,0,0,maxx,maxy,\
0,0,0,maxy,bitmap1,ADDR bminf,DIB_RGB_COLORS
mov eax,maxx
imul maxy
lea eax,[eax+eax*2]
invoke RtlZeroMemory,bitmap1,eax
r2:
inc fcount ; count the frames
fild flash
fmul flfactor
fistp flash
invoke Sleep,5 ; control, if frames rate goes too high
mov eax,stop
test eax,eax
jz lp1
invoke ReleaseDC,hwnd,wnddc
invoke HeapFree,hHeap,0,bitmap1
invoke HeapFree,hHeap,0,bitmap2
invoke HeapFree,hHeap,0,hFShells
mov idThread1,-1
invoke ExitThread,2003
hlt ; ...! i8085 memories
; -------------------------------------------------------------------------
.data
fps db 64 dup (0)
fmat db "fps = %u [www.ronybc.8k.com]",0
.code
MoniThread:
invoke Sleep,1000
invoke wsprintf,ADDR fps,ADDR fmat,fcount
invoke SetWindowText,hwnd,ADDR fps
xor eax,eax
mov fcount,eax
mov eax,stop