[C] hello world & compiler

Ich habe mir von 2 unterschiedlichen C compilern ein hello world Programm erstellen lassen mit Textausgabe per Msgbox.

Code:
#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nCmdShow)
{
    MessageBox(NULL, "Goodbye, cruel world!", "Note", MB_OK);
    return 0;
}

dann anschließend mit Olly nachgeschaut und eine riesen menge code mit bei entdeckt und ich dachte der compiler würd nur die user32.dll messageboxa sowie kernel32.exitprocess dort reinstecken ?

Also 30kb sowie 9,5 kb sind doch groß, in asm ist das ein paar Zeiler. Habe ich etwas beim compilieren falsch gemacht ?
 
Ja, dieser neumodische C Krams lässt einen nur glauben, man wäre immer noch ganz nah an der Maschine - in Wirklichkeit wird der Programmierer aber ziemlich entmündigt *SCNR* ;)

Ich bekomme mit dem VC 10 standardmäßig eine 7KB Exe heraus.
Als Tipp: einfach mal IDA ansetzen und schauen, was da noch rumschwirrt.

C setzt einige Dinge bzw. eine Umgebung voraus, die nicht unbedingt nach dem üblichen Programmstart vorliegt (wie man z.B in Olly sieht: der Executable-Loader mappt zwar die Exe in den Speicher, füllt die Importtabelle aus und setzt EIP auf den Entrypoint (was ohne weitere Linkeroptionen != Main ist) sowie ESP auf einen gültigen Speicherbereich, damit war's aber auch schon).

Beispiel:
int main(int argc, char *argv[]);
oder wie hier:
Code:
WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
    LPSTR lpCmdLine, int nCmdShow)
wo kommen eigentlich hInstance, CMDLine usw. her?
Die müssen vorher ermittelt werden.
Genauso werden auch Kommandozeilenparameter noch geparst.

Da gibt es halt einen Standard-Initialisierungsblock, der immer generiert wird. Außer "Kommandozeilenparsen" wird z.B noch Exceptionhandler gesetzt, Heap und globale Variablen initialisiert und alles für den eigentlichen "Main" Aufruf vorbereitet. Natürlich kann dabei was schief gehen und es sollte in einer mehr oder weniger aussagekräftigen Fehlermeldung resultieren -> auch das muss in den Code rein.

Betrachtet man das ganze in einem PE Editor, sieht man zudem dass es i.d.R 4-5 Sections gibt. Je nach FileAlignment belegen diese mindestens 512 Bytes.
Z.B bei der 7KB MS Executable:
PE Header: 1KB
.text mit dem eigentlichen Code. Größe: 2.5KB
.rdata mit der Meldung und Imports sowie ImportTable: 2KB
.data für die Variablen (auch wenn es nur 2-3 interne, globale Variablen sind): 0.5KB
.rsrc mit dem Manifest http://de.wikipedia.org/wiki/Manifest-Datei: 0.5K

Geht natürlich auch kleiner (1KB), wird aber ziemlich compilerspezifisch.
Im Anhang ein Beispiel für MS VC. Die Make.bat sollte man aus der VisualStudio Console/Eingabeaufforderung(sollte im Startmenü rumschwirren) ausführen, dann sollten die nötigen Umgebungsvariablen/Pfade gesetzt sein.
Alternativ reicht auch die "normale" CMD, wenn man in dieser vorher "Installationspfad\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" ausführt.


Oder man probiert den Tiny C Compiler: http://bellard.org/tcc/

Wobei es bei "realen" Anwendungen auf die +30KB nun nicht wirklich ankommt und ganz andere Dinge im Vordergrund stehen sollen ;)
 
Zurück
Oben