Saya sering mengulangi bahwa .NET Core adalah open source dan berfungsi "di mana-mana." MonoGame, Unity, Apple Watch, Raspberry Pi dan mikrokontroler, selusin Linux, Windows dan sebagainya. Sudah banyak.
Tetapi seseorang masih belum cukup.
Michal Strehowski ingin meluncurkan C # di
mana -
mana .
C # pada Windows 3.11Dia menjalankan kode C # pada dua sistem "tidak mungkin" yang sekarang melengkapi definisi kita tentang "bekerja di mana-mana." Meskipun ini adalah eksperimen yang menyenangkan (jangan ulangi dalam produksi), mereka menekankan kemampuan teknis dan fleksibilitas platform dasar Michal.
Menjalankan C # di bawah Windows 3.11
Dalam
tujuh tweet, Michal berbicara tentang bagaimana ia berhasil menjalankan kode C # di Windows 3.11. Aplikasi ini sederhana, hanya ada panggilan ke fungsi
MessageBoxA dengan tampilan kotak dialog yang sesuai, yang ada di Windows sejak hari pertama. Untuk memanggil fungsi dan mendapatkan
hasilnya , DllImport / PInvoke digunakan.
Saya pertama kali menunjukkan aplikasi ini untuk Windows 3.11 karena itu keren. Namun dalam kenyataannya, penulis mulai dari tempat di mana eksperimennya dengan DOS berakhir. Ini mengkompilasi kode C # asli, dan setelah itu aturan tidak ada lagi.
Dalam contoh ini, ini berjalan pada platform Win16, bukan Win32. Namun, pada tahun 1992 (ya, saya hidup dan diprogram saat itu, dan menggunakannya dalam proyek saya!) Ada jembatan teknologi tertentu yang disebut
Win32s : subset dari API Windows NT yang porting kembali ke Windows 3.11. Oleh karena itu, dengan mempertimbangkan beberapa batasan, Anda dapat menulis kode 32-bit dan mengakses Win32 dari Win16.
Michal menyadari bahwa file objek yang dibuat oleh kompiler CoreRT AOT pada tahun 2020 dapat dirakit oleh linker dari sampel Visual C ++ 2.0 tahun 1994. Hasilnya adalah kode mesin yang terhubung dengan antarmuka Win32 yang berjalan pada Windows 3.11 16-bit. Keajaiban. Hormati Michalu.
Aplikasi Hello World C # yang sederhanaMenjalankan C # pada 8K di bawah DOS
Saya telah menulis tentang
executable mandiri .NET Core 3.x sebelumnya, saya penggemar ini. Aplikasi saya sudah berkurang hingga 28 megabyte. Ini cukup sedikit, mengingat bahwa itu termasuk runtime .NET dan banyak sumber daya lainnya. Tentu saja, seseorang tidak boleh menilai VM / runtime berdasarkan ukuran dari program sekecil mungkin, tetapi Michal
ingin melihat sampai batas mana Anda bisa pergi - dan menetapkan target 8000 byte!
Program ini bekerja dalam
mode teks, yang menurut saya bagus . Ini juga menghilangkan kebutuhan akan pemulung, karena tidak ada alokasi sumber daya. Ini berarti Anda tidak dapat menggunakan yang
baru di mana pun. Tidak ada tipe referensi.
Untuk mendeklarasikan array statis, ia menggunakan bidang
fixed char []
: mereka harus hidup di stack, dan kami memiliki stack
kecil .
Tentu saja, ketika Anda mencoba membuat semacam .NET yang dapat dieksekusi, Anda awalnya mendapatkan file 65 megabyte, yang termasuk aplikasi, runtime, dan perpustakaan standar.
dotnet publish -r win-x64 -c Release
Anda dapat menggunakan
ILLinker dan PublishedTrimmed untuk mengoptimalkan Pemangkasan Pohon dari .NET Core 3.x, tetapi dengan cara ini Anda mengurangi file menjadi hanya 25 megabyte.
Dia mencoba menggunakan Mono dan mkbundle, membawa ukuran menjadi 18,2 megabita, tetapi kemudian menangkap kesalahan. Dan runtime masih ada.
Dengan demikian, satu-satunya runtime yang cocok adalah CoreRT, yang tidak termasuk mesin virtual, tetapi hanya fungsi tambahan.
dotnet publish -r win-x64 -c Release /p:Mode=CoreRT
Jadi dia mendapat 4,7 megabita, tetapi masih terlalu banyak. Dengan beberapa pengaturan, Anda dapat berjalan hingga 3 megabyte. Anda dapat sepenuhnya memperpanjang pantulan dan mencapai 1,2 megabita. Sekarang akan muat di floppy disk!
dotnet publish -r win-x64 -c Release /p:Mode=CoreRT-ReflectionFree
Ukuran satu megabyte ini tampaknya seperti batas keras untuk .NET SDK saja.
Di sinilah Michal
menjauh dari alat standar . Itu melakukan
rintisan implementasi ulang untuk tipe dasar Sistem ! Kemudian ia mengkompilasi ulang dengan beberapa switch ajaib sehingga hanya versi IL dari executable yang dirilis.
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
Kemudian ia meneruskan ini ke CoreRT untuk mendapatkan kode asli.
ilc.exe zerosnake.ilexe -o zerosnake.obj --systemmodule zerosnake --Os -g
Dan inilah kita.
βSekarang kita memiliki zerosnake.obj - file objek standar, tidak berbeda dengan file objek yang dibuat oleh kompiler asli lain, seperti C atau C ++. Langkah terakhir adalah menyatukannya. β
Beberapa trik lagi - dan hasilnya 27 KB! Kemudian ia menghapus beberapa switch dari linker untuk menonaktifkan dan menghapus berbagai hal menggunakan metode yang sama yang digunakan pengembang assembler, menghasilkan 8176 byte. Thriller Epik.
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
Ikuti
Michal di
Twitter dan bertepuk tangan untuknya.