Compiler mit kleinsten Executables



  • Ich bin persönlich Fan von besonders kleinen Executables. Mein Lieblingsprogramm dafür ist natürlich Hello World. Da wollte ich wissen welcher Compiler das kleinste C/C++-"Hello World" erstellen kann.

    1.) Hello World mit dem C/C++-Standard.
    2.) Hello World mit C/C++ - muss nicht Standard sein.

    Das ganze soll in der Win32-Konsole laufen. Jegliche Optimierungen sind ausdrücklich erlaubt.

    Mein kleinstes Hello World ist derzeit 1536Byte groß.

    MfG SideWinder



  • Hi!!!

    Bin leider net so gut wie du 😉

    Meine "Hallo Welt" Win32-Konsolenanwendung hat 3.104 Bytes.

    Die kleinste Hallo Welt Anwendung, die ich mit einem C Compiler überhaupt hinkriege ist eine Binary für den TI-92(Plus) mit einer Motorola 68k CPU (12MHz). Sie hat eine groesse von 369 Bytes.

    cu,
    Lukas

    PS: Schick mir mal deine zu, aber mach bitte noch ein.

    rewind(stdin); 
    getchar();
    

    mit rein, danke. Ich schicke dir dann auch meine zu. [url=mailto:consystor@web.de">consystor@web.de[/url]

    [ Dieser Beitrag wurde am 09.06.2002 um 13:59 Uhr von Consystor editiert. ]



  • hm
    mein gcc 2.95 schafft mit normalen (dynamischen lining) eine grösse von genau 5710 byte 🙂 und mit borland c++ builder 7000 byte



  • Hat man bei diesen Compilern, ebenfalls die Möglichkeit wie auch beim MSVC, das Projekt anzupassen? Das heißt, den Compiler auf minimale Größe zu trimmen?

    MfG SideWinder



  • Original erstellt von SideWinder:
    **Mein kleinstes Hello World ist derzeit 1536Byte groß.
    **

    verrätst du uns, mit welchen compiler und mit welchen tricks du das geschafft hast 🙂 ?



  • Jo, das verrate ich gerne - Compiler ist ganz genau der "Microsoft Visual C/C++ 6.0 Professional Edition Service Pack 3.0".

    Der Compiler ist auf Release gestellt. Der Code sieht so aus:

    // Weitere Optimierungen (die meisten Optimierungen hab ich schon in den Projekteinstellungen des MSVC vorgenommen):
    #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
    
    //#include <iostream>
    //#include <stdio.h>
    #include <windows.h>
    
    int main ()
    {
        // Standard-C++-Variante (benötigt mehr Speicherplatz):
        //std::cout << "Hello World";
    
        // Standard-C-Variante (gleich groß wie die Win-Con-Variante):
        //printf ( "Hello World" );
    
        // Windows-Konsolen-Variante:
        DWORD dw1 ( 0 );
        WriteConsole ( GetStdHandle ( STD_OUTPUT_HANDLE ) , "Hello World" , 11 , &dw1 , 0 );
    
        return ( 0 );
    }
    

    Die genauen Projekteinstellungen kann ich dir jetzt nicht geben, da ich unter Win98 im Netz bin (bei Win2k hats was mit dem I-Net).

    MfG SideWinder





  • @Consystor: Jo, ich schick dir meinen File. Kommt allerdings ohne der Abfrage. Musst halt auf der cmd.exe das Eigenschaftsfenster öffnen und "Sofortiges Schließen nach beenden" (oder so ähnlich) deaktiveren.

    MfG SideWinder



  • @xcvb: Sieht gut aus, werd ich mir auch mal anschauen!

    MfG SideWinder



  • Zugegeben, es entspricht nicht den Vorgaben aber meine 50 Bytes schlägt so schnell keiner:

    B4 02 B2 48 CD 21 B2 65 CD 21 B2 6C CD 21 B2 6C
    CD 21 B2 6F CD 21 B2 20 CD 21 B2 57 CD 21 B2 6F
    CD 21 B2 72 CD 21 B2 6C CD 21 B2 64 CD 21 B4 B2
    CD 21

    Im Hexeditor eingeben, mit der Endung .com speichern, von der Konsole aus aufrufen et voila: Hello World

    #include <fstream>
    #include <string>
    
    #define INT     0xCD
    #define MOV_AH  0xB4
    #define MOV_DL  0xB2
    
    int main(int argc, char* argv[]) {
     int i;
     char ch;
     string sText, sCode;
    
     sCode  = MOV_AH;
     sCode += 0x02;
    
     if (argc == 3)
     {
      ifstream in(argv[1], ios::in | ios::nocreate | ios::binary);
    
      while (!in.eof())
      {
       ch = in.get();
       i = ch;
       if (!in.eof())
       {
         sCode += MOV_DL;
         sCode += ch;
         sCode += INT;
         sCode += 0x21;
       }
      }
    
      sCode += MOV_AH;
      sCode += 0x4C;
      sCode += INT;
      sCode += 0x21;
    
      ofstream out(argv[2], ios::out | ios::binary);
      out << sCode;
     }
     else
     {
      cout << "Usage: txt2com [file.txt] [file.com]" << endl;
     }
    
     return 0;
    }
    


  • Hi!!!

    Naja, ich würde sagen, dass deine 50 Bytes super sind, aber nicht perfekt:

    Das hier sind 24 Bytes:
    --- START ---
    b4 09 ba 0b 01 cd 21 b4 4c cd 21 48 61 6c 6c 6f 20 57 65 6c 74 0a 0d 24
    --- ENDE  ---
    
    oder 22 Bytes (ohne lf und cr)
    --- START ---
    b4 09 ba 0b 01 cd 21 b4 4c cd 21 48 61 6c 6c 6f 20 57 65 6c 74 24 
    --- ENDE  ---
    

    In Hexeditor eingeben, als Hallo.com speichern und ausführen.

    cu und machs gut,
    Lukas

    PS:

    Habe dann auch noch den Code über mir etwas geändert.
    So kriegt jeder die kleineste Datei hin!

    #include <string>
    #include <fstream>
    
    #define INT     0xCD
    #define MOV_AH  0xB4
    #define MOV_DX  0xBA
    
    using namespace std;
    
    int main(int argc, char* argv[]) {
     int i;
     char ch;
     string sText;
     string sCode;
    
     if (argc == 3)
     {
      ifstream in(argv[1], ios::in | ios::nocreate | ios::binary);
    
      sCode += MOV_AH;
      sCode += 0x09;
      sCode += MOV_DX;
      sCode += 0x0B;
      sCode += 0x01;
      sCode += INT;
      sCode += 0x21;
      sCode += MOV_AH;
      sCode += 0x4C;
      sCode += INT;
      sCode += 0x21;
    
      while (!in.eof())
      {
       ch = in.get();
       sCode += ch;
      }
    
      sCode += '$';
    
      ofstream out(argv[2], ios::out | ios::binary);
      out << sCode;
     }
     else
     {
      cout << "Usage: txt2com [file.txt] [file.com]" << endl;
     }
    
     return 0;
    }
    

    cu und viel Spass beim Coden,
    Lukas

    [ Dieser Beitrag wurde am 09.06.2002 um 22:37 Uhr von Consystor editiert. ]



  • 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 geschrieben

    Allerdings 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.


Anmelden zum Antworten