Compiler mit kleinsten Executables
-
Meinen Glückwunsch... Eine schöne Demonstration wie schön man mit Hexeditor und Opcodetabelle programmieren kann.
-
MEEGAAA THNNNX FÜRS LOOOB!!!
Aber die Initiative ging von Dir aus!!!
cu,
Lukas
-
Mhm, also kleiner als 1.024 Bytes bekomme ich es nicht
1KB ist einfach, aber da will dann nichtmal mehr upx packen
-
Wir wollten eigentlich keine Optimierungen mit irgendwelchen Hex-Editoren ... da erfahr ich nicht viel über die Übertaktmöglichkeiten von Compilern ;).
@Shade: Du hast Hello World auf 1024Bytes - compiliert oder nachbearbeitet?
BTW: Tip für alle Coder: Die <iostream> in ein Projekt einzubinden ist sehr, sehr teurer. Man sollte lieber über die C-Standard-Variante oder über die WinAPI gehen.
MfG SideWinder
-
Original erstellt von SideWinder:
@Shade: Du hast Hello World auf 1024Bytes - compiliert oder nachbearbeitet?Faul wie ich bin, habe ich lediglich deine Version optimiert.
Aber 300 Bytes mehr oder weniger sind ja egal ich wollt nur etwas aufschneiden
Der 'Trick' liegt darin, keine default librarys einzubinden. Man braucht lediglich die die kernel32.lib fuer die 2 Funktionen.
dadurch muss man statt main halt mainCRTStartup schreiben, aber das sollte egal sein.
Kleiner gehts AFAIK nicht mehr.
Vor einiger Zeit habe ich fuer GermanDevNet einen kleinen Artikel darueber geschriebenAllerdings habe ich dort das 'merge' von Segmenten nicht behandelt, da das IMHO zu fehleranfaellig ist, als das ich es wirklich verwenden wuerde (es sei denn fuer so kleine Optimierungsspielchen wie hier)
[nachtrag]Natuerlich auf 1.024 Bytes Compiliert.
upx will es naemlich ned mehr komprimieren :([/nachtrag][ Dieser Beitrag wurde am 10.06.2002 um 14:44 Uhr von Shade Of Mine editiert. ]
-
Kleiner gehts AFAIK nicht mehr.
Sag niemals nie...
Werd mir noch den Artikel auf der MS-Page durchlesen, vielleicht lässt sich ja noch was rauskratzen :).
MfG SideWinder
Edit: Hab gar nicht gewusst, dass du Anton heißt.
[ Dieser Beitrag wurde am 10.06.2002 um 14:52 Uhr von SideWinder editiert. ]
-
Ich fasse mal zusammen, was es alles so gibt:
// Vorcompilierter Header "smallwin.h" #ifndef SMALLWIN_H #define SMALLWIN_H #ifdef NDEBUG #pragma optimize ( "gsy" , on ) #pragma comment ( linker , "/RELEASE" ) #ifdef _MERGE_RDATA_ #pragma comment ( linker , "/merge:.rdata=.data" ) #endif #pragma comment ( linker , "/merge:.text=.data" ) #pragma comment ( linker , "/merge:.reloc=.data" ) #pragma comment ( linker , "/ignore:4078" ) #if _MSC_VER >= 1000 #pragma comment ( linker , "/opt:nowin98" ) #endif #endif #define WIN32_LEAN_AND_MEAN #include <windows.h> int WINAPI WinMainCRTStartup () { // Wir bieten absolut keinen Komfort, die Parameter werden nicht übergeben. iCmdShow wird mit Standardwerten gefüllt. int Main ( WinMain ( GetModuleHandle ( 0 ) , 0 , 0 , SW_SHOWDEFAULT ) ); ExitProcess ( Main ); return ( Main ); } #endif // Quellcodedatei "hw.cpp" #include "smallwin.h" int WINAPI WinMain ( HINSTANCE hInst , HINSTANCE hPrev , LPSTR szCmdLine , int iCmdShow ) { DWORD dw1 ( 0 ); WriteConsole ( GetStdHandle ( STD_OUTPUT_HANDLE ) , "Hello World" , 11 , &dw1 , 0 ); return ( 0 ); }
Das ist so ziemlich das kleinste was man hin bekommen kann. Sogar die interne Startup-Funktion des Compilers wird frisch geschrieben: Das Ignorieren der Standardlibs wird dadurch aber zwingend.
Jetzt muss man nur noch die optimalen Linkereinstellungen finden.
MfG SideWinder
-
Das mit den Segmenten halt ich eher für unkritisch, weshalb ich eich bei größeren Progs wenig Angst hätte. Aber ne eigene Startup, die nochtmal die Konstruktoren globaler Objekte hochzeiht? Dan kann man nur in C machen.
-
@Consystor: Das Programmm ist nur 21 byte groß, wenn du zum Beenden ein int 20 benutzt.
-
@volkard: Bei Hello World hoffe ich ja doch noch ohne Konstruktoren auszukommen. Aber du hast recht bei größeren Projekten ist es ziemlich kritisch. Wie schaut das dann eigentlich aus? Muss ich da in jeden Konstruktor das Gleiche schreiben was auch der Compiler vorne reinschreiben würde? Oder wird der Konstruktor bei static-Objekten dann erst gar nicht aufgerufen, und es geht nach dem Motto selbst ist der Mann?
MfG SideWinder
-
Der Compiler baut Dir schon ne gobale Liste von void-Funktionen, die Du aufrufen sollst. Ganz gemein ist er der startup() gegenüber nicht.
-
Wo findet man die beim MSVC? In welchem Header findet man eigentlich überhaupt die normale Startup? Weiß das jemand?
MfG SideWinder
-
-
Header? Wird nicht benötigt, die Funktion zu deklarieren.
-
Original erstellt von volkard:
DAber ne eigene Startup, die nochtmal die Konstruktoren globaler Objekte hochzeiht? Dan kann man nur in C machen.In meinem Artikel habe ich die eigene Startup aber behandeln muessen, da ich nodefaultlib erklaeren wollte.
Natuerlich hat es absolut keinen Sinn die Standard Library NICHT zu linken. dann braucht man ja kein C/C++ mehr Programmieren.
Normalerweise tun es dynamisches Linken der msvcrt.lib bzw. dynamisches linken der MFC und ein /opt:nowin98
dass ganze mit upx gepackt und die groesse ist minimalhier gehts aber um extreme optimierung!
-
Weis denn niemand wo ich diese Funktionen finden kann?
MfG SideWinder
-
Ich weiß, dass ihr hier eigentlich nur über Compilerswitches reden wollt und keine Opcodes oder ähnliches hören wollt, aber ich konnte mich hier einfach nich zurückhalten meinen Senf dazu zu geben.
Also das kleinste Hello World für Windows, das ich je gesehen habe, war mit dem NASM erstellt und die compilierte Datei war nur ca. 650 bytes groß. Und dabei hätte man ruhig noch ein paar Bytes sparen können, denn da war noch ein wenig DOS Code für eine Message drin (die erscheint wenn man die EXE unter DOS startet, meist das typische "This program cannot be run under DOS").
Das kleinste Hello World für DOS (wahrscheinlich aber nur MS-DOS) ist folgendes:95 BA 07 01 CD 21 C3 68 65 6C 6C 6F 20 77 6F 72 6C 64 24
Ist wieder für eine COM Datei. 19 Bytes ohne CRLF. Das Ganze ist folgender ASM Code:
xchg ax,bp mov dx,offset msg int 21h retn msg DB "hello world$"
-
Von den 19 Bytes fällt ja das immer noch das meiste auf die "Hello World"-Nachricht. Aber wie gesagt, wir (eigentlich ich) will kein Assembler, kein Opt-Code, keine .com-Dateien.
Wie siehts eigentlich mit den Optimierungen noch aus, was benötigt jetzt noch immer so viel Platz?
MfG SideWinder
PS@malfunction: Ich würde mir Gedanken machen, deine Version weiter zu optimieren. Vielleicht schaffst du es ja den Text "Hello World" irgendwo auszulagern und die Auslagerung mit weniger Bytes zu öffnen?
-
@SideWinder: Ich glaube kaum, dass diese COM Datei noch kleiner geht. Das XCHG AX,BP (ein byte) ist ja schon ein kleiner undokumentierter Trick. Es ersetzt das MOV AH,09 (zwei bytes), weil das höherwertige Byte von BP zum Start des Programms aus irgendeinem komischen Grund immer gleich 09 ist.
Wenn ich den String auslagern soll, kann ich auch gleich den restlichen Code auslagern. Das wäre dann aber geschummelt. Da müsste dann ja nur ein Programm vorher ausgeführt werden, dass seinen eigenene Real Mode Interrupt installiert und dann bräuchte ich den im Hello World Proggie nur noch auszuführen -> 2 bytes
-
Wenn mans so sieht...aber im Grunde genommen habe ich bei der C++-Version auch nicht mehr gemacht. Habe vieles aus der MSVCRT.dll genommen, hab MFC dynamisch gelinkt, etc - andererseits sind die grundlegenden Dinge noch immer da.
MfG SideWinder
PS: Hello World mit 2Bytes ... kleiner wirds dann wohl keiner mehr schaffen...