Wenn .NET überall funktioniert, dann auch unter Windows 3.11 und DOS

Ich wiederhole oft, dass .NET Core Open Source ist und "überall" funktioniert. MonoGame, Unity, Apple Watch, Raspberry Pi und Mikrocontroller, ein Dutzend Linux, Windows und so weiter. Schon viel.

Aber jemand ist immer noch nicht genug. Michal Strehowski will C # wirklich überall starten.


C # unter Windows 3.11

Er hat den C # -Code auf zwei "unmöglichen" Systemen ausgeführt, die jetzt unsere Definition von "überall funktionieren" ergänzen. Obwohl es sich um unterhaltsame Experimente handelt (wiederholen Sie sie in der Produktion nicht), betonen sie sowohl Michals technische Fähigkeiten als auch die Flexibilität der Basisplattform.

Ausführen von C # unter Windows 3.11


In sieben Tweets spricht Michal darüber, wie er es geschafft hat, C # -Code unter Windows 3.11 auszuführen. Die Anwendung ist einfach, es wird nur die MessageBoxA- Funktion mit der Anzeige des entsprechenden Dialogfelds aufgerufen, das sich ab den ersten Tagen unter Windows befindet. Um die Funktion aufzurufen und das Ergebnis zu erhalten , wird DllImport / PInvoke verwendet.

Ich habe diese Anwendung zum ersten Mal für Windows 3.11 gezeigt, weil sie cool ist. In Wirklichkeit begann der Autor an dem Ort, an dem sein Experiment mit DOS endete. Es kompiliert nativen C # -Code und danach existieren die Regeln nicht mehr.

In diesem Beispiel wird es auf der Win16-Plattform und nicht auf Win32 ausgeführt. 1992 (ja, ich habe damals gelebt und programmiert und es in meinen Projekten verwendet!) Gab es jedoch eine bestimmte technologische Brücke namens Win32s : eine Teilmenge der Windows NT-APIs, die auf Windows 3.11 zurückportiert wurden. Unter Berücksichtigung einiger Einschränkungen können Sie daher 32-Bit-Code schreiben und von Win16 aus auf Win32 zugreifen.

Michal erkannte, dass die vom CoreRT AOT-Compiler im Jahr 2020 erstellten Objektdateien vom Linker aus dem Visual C ++ 2.0-Beispiel von 1994 zusammengesetzt werden konnten. Das Ergebnis ist Maschinencode, der mit Win32s-Schnittstellen verknüpft ist, die unter 16-Bit-Windows 3.11 ausgeführt werden. Die Magie. Respektieren Sie Michalu.


Einfache Hello World C # -Anwendung

Ausführen von C # bei 8 KB unter DOS


Ich habe bereits über eigenständige ausführbare .NET Core 3.x-Dateien geschrieben . Ich bin ein großer Fan davon. Meine Anwendung wurde bereits auf 28 Megabyte reduziert. Dies ist ziemlich viel, da es die .NET-Laufzeit und viele andere Ressourcen enthält. Natürlich sollten Sie eine VM / Laufzeit nicht nach der Größe des minimal möglichen Programms beurteilen, aber Michal wollte sehen, bis zu welchem ​​Limit Sie gehen können - und ein Ziel von 8000 Bytes festlegen!

Das Programm arbeitet im Textmodus, was meiner Meinung nach großartig ist . Außerdem ist kein Garbage Collector mehr erforderlich, da keine Ressourcenzuweisung erfolgt. Dies bedeutet, dass Sie new nirgendwo verwenden können. Keine Referenztypen.

Um statische Arrays zu deklarieren, werden fixed char [] -Felder verwendet: Sie müssen sich auf dem Stapel befinden, und wir haben einen kleinen Stapel.

Wenn Sie versuchen, eine eigenständige .NET-Datei ausführbar zu machen, erhalten Sie zunächst eine 65-Megabyte-Datei, die die Anwendung, die Laufzeit und die Standardbibliotheken enthält.

dotnet publish -r win-x64 -c Release

Sie können ILLinker und PublishedTrimmed verwenden, um das Tree Trimming von .NET Core 3.x aus zu optimieren. Auf diese Weise reduzieren Sie die Datei jedoch auf nur 25 Megabyte.

Er hat versucht, Mono und mkbundle zu verwenden und die Größe auf 18,2 Megabyte zu bringen, hat dann aber einen Fehler festgestellt. Und die Laufzeit ist noch da.

Die einzig geeignete Laufzeit war daher CoreRT, das keine virtuelle Maschine, sondern nur Hilfsfunktionen enthält.

dotnet publish -r win-x64 -c Release /p:Mode=CoreRT

Er hat also 4,7 Megabyte, aber es ist immer noch zu viel. Bei einigen Einstellungen können Sie bis zu 3 Megabyte gehen. Sie können die Reflektion vollständig erweitern und 1,2 Megabyte erreichen. Jetzt passt es auf eine Diskette!

dotnet publish -r win-x64 -c Release /p:Mode=CoreRT-ReflectionFree

Diese Größe von einem Megabyte scheint nur für das .NET SDK eine harte Grenze zu sein.

Hier entfernt sich Michal von Standardwerkzeugen . Es führt einen Neuimplementierungs-Stub für die grundlegenden Systemtypen aus ! Anschließend wird es mit einigen magischen Schaltern neu kompiliert, sodass nur die IL-Version der ausführbaren Datei freigegeben wird.

csc.exe /debug /O /noconfig /nostdlib /runtimemetadataversion:v4.0.30319 MiniBCL.cs Game\FrameBuffer.cs Game\Random.cs Game\Game.cs Game\Snake.cs Pal\Thread.Windows.cs Pal\Environment.Windows.cs Pal\Console.Windows.cs /out:zerosnake.ilexe /langversion:latest /unsafe

Dann übergibt es dies an CoreRT, um den nativen Code zu erhalten.

ilc.exe zerosnake.ilexe -o zerosnake.obj --systemmodule zerosnake --Os -g

Und hier sind wir.

„Jetzt haben wir zerosnake.obj - eine Standardobjektdatei, die sich nicht von den Objektdateien unterscheidet, die von anderen nativen Compilern wie C oder C ++ erstellt wurden. Der letzte Schritt ist, es zusammenzustellen. “

Noch ein paar Tricks - und die Ausgabe ist 27 KB! Anschließend entfernt er mehrere Schalter aus dem Linker, um verschiedene Elemente mit denselben Methoden zu deaktivieren und zu entfernen, die die Assembler-Entwickler verwenden. Es bleiben 8176 Byte übrig. Epischer Thriller.

link.exe /debug:full /subsystem:console zerosnake.obj /entry:__managed__Main kernel32.lib ucrt.lib /merge:.modules=.rdata /merge:.pdata=.rdata /incremental:no /DYNAMICBASE:NO /filealign:16 /align:16

Folge Michal auf Twitter und applaudiere ihm.

Source: https://habr.com/ru/post/de485268/


All Articles