Monthly Archives: May 2020

Assembler di browser berbasis Keystone dengan WebAssembly

Sebenarnya saat ini saya sedang sibuk dengan banyak hal, tapi karena sedang berduka, saya ingin melakukan sesuatu untuk mengalihkan pikiran. Bapak saya suka membongkar mobil untuk mengalihkan pikiran, sedangkan saya lebih suka memprogram sesuatu yang tidak berhubungan dengan pekerjaan. Hasilnya: hari ini saya mengkompilasi framework Keystone dengan target WebAssembly (Wasm) lalu memberi interface HTML dengan Preact (alternatif React yang ukurannya jauh lebih kecil).

Assembler ini bisa diakses online di https://asm.x32.dev dan sourcenya saya berikan di https://github.com/yohanes/online-assembler . Aplikasinya bisa diakses dengan semua browser modern (Safari, Chrome, Firefix, Edge), termasuk juga mobile browser (sudah ditest di iOS 13 dan Android 10).

WebAssembly (Wasam)

Supaya tidak bingung dengan penjelasan assembler dan webassembly, akan saya jelaskan apa itu WebAssembly (biasa disingkat dengan Wasm). WebAssembly adalah format instruksi biner untuk virtual machine (bisa dibayangkan seperti bytecode Java) . Saat ini target utamanya adalah web browser (saat ini sudah disupport di Firefox, Google Chrome, Safari dan Edge). Di masa depan web assembly ini dihrapkan akan bisa dipakai juga di aplikasi desktop maupun server.

Sekarang ini sudah ada compiler supaya kita bisa mengkompilasi bahasa C, C++, Rust, dsb ke kode WebAssembly. Setelah dikompilasi, kodenya bisa dijalankan di browser. Sayangnya API web browser tidak bisa diakses oleh kode web assembly, jadi diperlukan jembatan berupa kode JavaScript.

Keystone

Keystone merupakan library assembler untuk berbagai arsitektur. Diberikan teks assembly, kita bisa memakai library ini untuk mengubahnya menjadi bahasa mesin. Keystone ini sebenarnya memakai bagian dari libary LLVM, tapi diekstrak bagian assemblernya saja. LLVM sendiri merupakan proyek infrastruktur compiler yang memiliki banyak fitur (parser, optimizer, assembler, linker, debugger, dsb) tapi terlalu kompleks dan terlalu besar jika hanya ingin fitur assemblernya saja.

Untuk keperluan development program dalam assembly, Keystone ini belum terlalu layak pakai karena banyak bugnya dan tidak memiliki fitur macro yang ada di banyak assembler modern. Untuk development, sebaiknya pakai saja assembler dari berbagai compiler yang ada. Keystone ini lebih terpakai untuk riset security, patching program, dan berbagai fungsi kecil lain yang overkill jika memakai assembler lengkap dari sebuah compiler. Contoh pemakaian Keystone adalah untuk menyelesaikan soal CTF semacam yang saya selesaikan dua tahun yang lalu.

Jadi supaya jelas: assembly di WebAssembly tidak berhubungan dengan assembler di library Keystone (saat ini keystone belum mendukung web assembly).

EMSDK

Dengan menggunakan emscripten SDK (emsdk), sekarang kita bisa mengkompilasi banyak library dan program yang ditulis dalam bahasa C/C++ dengan target Web Assembly dengan relatif mudah. Jika program atau library memakai configure, kita bisa menjalankan emconfigure ./configure dan jika memakai cmake, kita bisa menjalankan emcmake cmake. Program emconfigure dan emcmake merupakan wrapper, agar ketika configure/cmake dijalankan, maka compiler dan library yang akan dipakai adalah untuk target WASM.

Tentunya tidak semua program dan library bisa dikompilasi dengan mudah. Contoh kode yang tidak bisa dicompile langsung: kode yang butuh library lain, kode yang butuh akses hardware, kode yang butuh akses layanan sistem operasi tertentu, kode yang memakai kode assembly dalam Intel x86 atau ARM, dan masih banyak lagi kasus khusus lain. Dalam kasus seperti ini, kita perlu melakukan porting manual.

Selain mengkompilasi file C menjadi WASM, emsdk juga menghasilkan file Javascript yang gunanya menjadi jembatan antara Javascript dan WASM. Jembatan ini dua arah: kode C yang memanggil fungsi library standar seperti printf akan memanggil kode JavaScript (misalnya kita arahkan menjadi memanggil console.log), dan kita bisa memanggil kode C dari Javascript.

Optimasi ukuran

Saat ini kode yang dihasilkan dari EMSDK masih belum efisien. Library Keystone ketika dicompile dengan target Web Assembly, hasilnya menjadi file 9.7 megabyte. Saat ini ada proyek lain bernama binaryen yang merupakan infrastruktur compiler untuk WebAssembly. Salah satu toolnya adalah wasm-opt yang dapat digunakan untuk mengoptimasi bytecode WASM. Tool yang lain adalah disassembler Web Assembly (disassembler ini saya pakai untuk menyelesaikan soal CTF).

Setelah dioptimasi, library Keystone yang berukuran 9.7 megabyte berkurang menjadi 5.7 megabyte saja. Ketika didistribusikan, file ini masih akan dikompresi dengan gzip dan hasilnya menjadi 1.5 megabyte. Ukurannya memang tidak kecil, tapi kebanyakan foto dan video ukurannya juga sudah ratusan kilobyte.

User Interface

Bagian berikutnya yang perlu dilakukan adalah membuat user interface yang bagus untuk library yang kita compile tersebut. Untuk program yang memakai Simple DirectMedia Layer (SDL) dan OpenGL, kadang kita bisa langsung menjalankannya karena emsdk sudah menyediakan wrapper untuk API HTML Canvas dan WebGL. Sedangkan untuk aplikasi lain, kita perlu membuat interface HTML dan menggunakan JavaScript untuk memanggil kode C.

Alasan saya memporting Keystone agar bisa memakai assembler keystone terbaru dari browser. Sudah ada yang membuat keystone.js tapi sudah lama tidak diupdate.

Tadinya saya hanya ingin memakai HTML + Javascript murni saja untuk user interfacenya. Tapi setelah saya pertimbangkan lagi, memakai library Javascript akan membuat kodenya jadi lebih terstruktur. Tadinya saya akan memakai React, tapi aplikasi kecil dalam React butuh ratusan kilobyte (terutama karena bagian ReactDOM). Jadi saya memakai Preact yang memakai API yang (hampir) sama dengan React tapi ukurannya hanya 9 kilobyte saja (bahkan hanya 4 kilobyte setelah dikompres).

Development JavaScript Modern biasanya dilakukan dengan menggunakan build system, tapi sebenarnya tidak wajib. Karena program saya ini sangat kecil, saya putuskan untuk tidak memakai build system. Semua kode langsung masuk ke file HTML dan JS. Karena saya memakai WASM, browser harus cukup modern, jadi saya bisa memakai berbagai fitur HTML/JS terbaru tanpa butuh berbagai library polyfill.

Penutup

Salah satu cara belajar teknologi Web Assembly adalah dengan memporting berbagai library dan program ke browser dan membuat atau menyesuaikan user interface agar berjalan di browser. Bahasa C/C++ sudah ada sejak lama, dan sudah banyak hal menarik yang dibuat dalam C, berbagai kode yang sudah ada ini bisa dibawa ke browser dan dieksekusi langsung tanpa butuh server (server hanya sekedar untuk menyimpan file saja, tidak untuk eksekusinya).

Semoga artikel singkat ini berguna untuk memulai eksplorasi Web Assembly, dan semoga assembler onlinenya juga bisa terpakai di masa depan, baik untuk saya sendiri maupun orang lain.

Bahasa Pemrograman BASIC

Setelah membahas Forth dan juga Lua, kali ini saya akan membahas bahasa BASIC (Beginners’ All-purpose Symbolic Instruction Code). Bahasa BASIC ini merupakan bahasa yang sudah ada lama sekali (sejak 1964), tapi ada beberapa hal yang baru-baru ini terjadi yang membuat saya ingin menuliskan tentang bahasa BASIC:

Tiga hal pertama tersebut menunjukkan bahwa:

  • Minat terhadap bahasa lama (BASIC dan COBOL) ternyata masih cukup besar
  • Bahasa-bahasa lama ini masih terpakai (tapi dalam artikel ini saya hanya membahas BASIC)

Setelah membaca mengenai SmileBASIC 4, saya segera membeli softwarenya dari Nintendo Shop. Harga softwarenya 25 USD (masih lebih murah dari kebanyakan game di Nintendo Shop), plus harus membeli slot upload seharga 5 USD jika kita ingin mengupload program kita ke server SmileBASIC.

Setelah mencoba-coba lagi Smile BASIC, ternyata memang bahasa BASIC ini masih bisa membuat saya tersenyum Saya masih bisa membuat program dalam bahasa ini dengan cepat, dan bisa membuat animasi sederhana untuk Joshua dalam waktu sangat sebentar (dalam hitungan menit). Saya juga teringat dulu masa-masa saya belajar sendiri bahasa BASIC. Jadi saya ingin bercerita lebih jauh mengenai bahasa BASIC ini.

Animasi huruf yang dibuat hanya dalam beberapa menit

Di masa kejayaannya, BASIC ada di mana-mana:

  • Ada novel petualangan yang di dalamnya ada kode bahasa BASIC (pernah saya tulis di sini)
  • Berbagai majalah memberikan listing program bahasa BASIC
  • Berbagai buku teks mahasiswa juga diberi kode dalam bahasa BASIC untuk bisa langsung dicoba

Banyak orang menghindari bahasa BASIC karena sifatnya yang tidak terstruktur. Ini memang benar untuk BASIC generasi pertama. Ilmuan komputer Djikstra sering dikutip karena mengkritik BASIC, begini katanya:

“It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration”,

Edsger W. Dijkstra – “How do we tell truths that might hurt” . Selected Writings on Computing: A Personal Perspective

Tapi sebenarnya di tulisan lengkapnya, Djikstra tidak cuma mengkritik BASIC, tapi juga bahasa lain seperti FORTRAN dan COBOL yang sampai saat ini masih dipakai.

Setelah kritiknya itu, sebenarnya bahasa BASIC masih berkembang dan generasi berikutnya sebenarnya sudah cocok menjadi bahasa pemula dan bisa digunakan untuk mengajarkan berbagai konsep pemrograman yang baik.

Beberapa Generasi

Bahasa generasi pertama memakai nomor baris, konsep fungsi dan subrutinnya terbatas, dan sulit membuat struktur data kompleks. Contoh keterbatasan adalah: fungsi hanya sekedar formula, tidak bisa membuat fungsi rekursif. Subrutin memakai nomor baris (tidak memakai nama) dan tidak memiliki variabel lokal. Beberapa implementasi bahkan tidak memiliki DEF untuk membuat fungsi. Contoh versi BASIC ini adalah yang ada pada ROM PC XT, dan ROM berbagai hardware komputer rumah tahun 80an.

Seperti apa sih program BASIC ini? ini adalah program sangat sederhana yang tidak berhenti menampilkan “HELLO WORLD”. Programnya mudah dimengerti: cetak tulisan hello world, dan berikutnya GOTO 10, artinya ulangi lagi baris 10, dst.

10 PRINT "HELLO WORLD"
20 GOTO 10

BASIC sangat populer sehingga pernah dibuat dua standard (ISO/ANSI) tentang bahasa BASIC (yang core dan yang full). Kedua standardnya hanya mencakup generasi pertama yang masih menggunakan nomor baris. Bahasa BASIC juga masuk ke banyak device yang bukan PC, misalnya game console dan juga kalkulator.

20161127_220343
Saya program HP 39gs untuk menampilkan hari pasaran dari sebuah tanggal

BASIC generasi kedua (Structured Basic) tidak lagi memakai nomor baris (walau beberapa versi secara opsional membolehkan nomor baris), mendukung fungsi dan subrutin dengan variabel lokal, dan mendukung user defined type (struct/record). Contoh BASIC generasi kedua adalah Microsoft QuickBasic.

Tanpa nomor baris, program hello world bisa mirip Python 2 (Python 3 mewajibkan kurung). Apalagi BASIC ini sifatnya tidak case sensitive, jadi PRINT sama dengan print.

print "hello world"

BASIC generasi ketiga sudah seperti bahasa pemrograman lainnya yang berbasis objek, hanya saja syntax-nya meniru BASIC yang lama. Contoh BASIC generasi ketiga ini adalah Visual Basic .NET. Tapi saat ini minat bahasa BASIC generasi terbaru sudah mulai berkurang, bahkan Microsoft sudah tidak akan menambah lagi fitur di Visual Basic.NET.

Menurut saya sendiri, BASIC generasi kedua ini sudah cukup ideal untuk berbagai aplikasi kecil dan program ukuran kecil yang fun. Jika ingin memprogram berorientasi objek, sekalian saja pakai Java/C#/Python atau bahasa lain.

Sederhana

Kenapa bahasa BASIC sempat populer dibandingkan bahasa lain? menurut saya ini gabungan beberapa hal. Masalah utama adalah Keterbatasan hardware: sulit membuat compiler dengan memori terbatas di hardware awal masa komputer personal (awal 1980an). Jadi alternatifnya adalah: memprogram dalam assembly, atau dalam bahasa lain yang sederhana. BASIC menang dibandingkan bahasa lain (misalnya FORTH yang pernah saya bahas di sini), karena sangat mudah dimengerti walaupun baik BASIC maupun FORTH keduanya merupakan bahasa yang interaktif.

Cassette Basic. Pengguna PC XT dulu akan ingat ini. Memori yang bisa diakses kurang dari 64kb

Kesederhanaan Bahasa BASIC ini bisa dilihat dari jumlah statement dasar yang dimiliki. Versi awal yang dikembangkan pencipta BASIC: John G. Kemeny dan Thomas E. Kurtz (disebut Darmouth BASIC) hanya punya 15 statement (LET, PRINT, END, DATA, READ, GOTO, IF, FOR/NEXT, GOSUB, RETURN, DIM, REM, STOP, DEF). Plus ada beberapa fungsi built in seperti misalnya ABS untuk mendapatkan nilai absolute atau SIN/COS/TAN untuk trigonomoetri.

Dengan kesederhanaan ini, mengimplementasikan interpreter BASIC bisa dilakukan dengan memori kecil. Salah satu kesuksesan awal Microsoft (waktu itu namanya masih Micro Soft, bukan satu kata) adalah produk interpeter BASIC yang ditulis oleh Bill Gates dalam assembly (kodenya sudah dibuka, ada di github). Bahkan di kode assembly yang relatif kecil, Bill Gates bisa menyembunyikan Easter Egg.

Kesederhanaan bahasa BASIC juga bisa digunakan sebagai latihan ketika mengimplementasikan sebuah interpreter. Saya sendiri pernah mengimplementasikan interpreter BASIC dalam JavaScript 10 tahun yang lalu (masih berfungsi ada sampai sekarang).

Instan

Kebanyakan implementasi BASIC, bahkan dari jaman PC XT dulu, eksekusinya hampir instan. Dari mengetik kode hingga berjalan tidak dibutuhkan waktu berdetik-detik atau bermenit-menit. Selain itu hampir semua implementasi BASIC menggabungkan editor dan interpreter, jadi mengetik, menjalankan program, dan bahkan mendebug bisa dilakukan di environment yang sama.

Experience memprogram BASIC ini menurut saya masih sulit ditemui di sistem lain, kecuali jika kita mendownload IDE super lengkap dengan ukuran besar. Bahkan berbagai IDE modern dengan fitur lengkap sering sulit dikonfigurasi.

Meskipun cycle untuk mengedit dan menjalankan program bisa cepat, tapi program yang ditulis dalam BASIC relatif lambat. Untungnya sejak awal sebagian besar implementasi BASIC bisa memanggil kode mesin.

Kode dalam bahasa BASIC umumnya dijalankan dalam sebuah interpreter, tapi sejak puluhan tahun yang lalu sudah ada banyak compiler Bahasa BASIC yang bisa menghasilkan native code. Jadi tidak benar jika bahasa BASIC pasti harus diinterpretasi.

Menengok implementasi BASIC Modern

Saat ini ada banyak implementasi BASIC modern, dan saya sudah mencoba cukup banyak. Saya tidak akan membahas semuanya, dan hanya yang menurut saya menarik saja.

QB64

QB64 ini open source dan meniru user interface QBasic/QuickBasic. QB64 tersedia untuk multi platform. Meskipun meniru QBasic, fitur-fitur baru yang dimiliki sangat banyak, termasuk untuk membuat aplikasi serius atau game 3D dan bahkan aplikasi Android. Sayangnya saya tidak suka implementasinya: kode ditranslasikan ke C, alalu dicompile dengan compiler C. Hasilnya: waktu kompilasinya lama, tidak bisa menjalankan program dengan instan seperti QBasic/QuickBasic. Bahkan saat ini versi terbaru dari github yang saya download gagal menjalankan aplikasi hello world.

Just BASIC

Just BASIC ini hanya tersedia di Windows, gratis tapi tidak open source. Kelebihannya dibandingkan solusi yang lain adalah: bisa digunakan untuk membuat aplikasi Windows yang memakai native control di Windows. Just BASIC memakai pendekatan interpreter, dan eksekusinya instan, ketika mengklik RUN, program akan langsung berjalan.

AppGameKit Classic

AppGameKit Classic adalah implementasi BASIC berbayar untuk membuat game. Saya mengenal AppGameKit ini dari Humble Bundle beberapa tahun lalu dan ternyata sampai saat ini masih terus diupdate. Harga penuh aplikasi AppGameKit relatif mahal, tapi sering bisa dibeli murah dengan berbagai diskon dan bundle dari berbagai situs. AppGameKit dapat dipakai untuk membuat game, baik desktop, web, maupun mobile.

Engine utama AppGameKit ini ditulis dalam C++, dan bisa dipanggil langsung dari C++ jika kita mau, tapi mode untuk menjalankan kode BASIC adalah interpretasi. Bahasa BASIC yang didukung adalah generasi 2, jadi kita bisa membuat tipe data sendiri, tapi tidak bisa memakai OOP.

Beberapa tahun lalu ketika mencoba ini, rasanya cukup fun. Cukup mudah membuat game sederhana. Bahkan ada mode sangat bagus untuk membuat game mobile: mode broadcast. Asalkan device Android kita ada di subnet yang sama, kita cukup menjalankan AppGameKit Player di Android, tekan Broadcast di PC, dan akan muncul gamenya di device Androidnya, instan.

SmileBASIC 4

Saya mendengar berita rilis SmileBASIC di Hacker News, jadi ini relatif baru buat saya. SmileBASIC ini juga tersedia untuk game console Nintendo 3DS. Walaupun sulit sekali memprogram dengan layar kecil 3DS, ternyata aplikasi ini cukup populer sehingga mereka membuat versi Nintendo Switchnya.

Bandingkan jumlah memorinya dengan PC XT

Nintendo Switch bisa dihubungkan ke monitor dengan HDMI dan bisa dihubungkan juga ke keyboard dan mouse USB (dan bahkan juga headset USB). Tanpa keyboard USB, kita bisa memprogram dengan keyboard di layar sentuh, tapi ini kurang efisien. Jadi selama saya mencoba SmileBASIC, saya selalu menggunakan keyboard dan mouse dan layar besar (SmileBASIC mendukung sampai dengan resolusi 1280×720).

AppGameKit mudah diprogram, tapi memiliki kelemahan: kita harus mencari sendiri asset (gambar, musik, efek suara) untuk game atau membeli pack terpisah. Sedangkan SmileBASIC memiliki ratusan sprite built in, puluhan music background built in, dan juga puluhan sound effect. Tersedia juga editor bitmap built in jika gambar yang ada tidak seperti yang kita mau.

Tapi SmileBASIC memiliki kelemahan dari segi fitur bahasa BASIC-nya. Meskipun menggunakan BASIC generasi 2 (tanpa line number), tapi SmileBASIC tidak mendukung user defined type.

Penutup

Bahasa BASIC memang sudah tidak terlalu banyak dipakai dibandingkan masa kejayaannya, tapi belajar bahasa ini cukup menyenangkan. Masih ada orang yang bisa mendapatkan uang dari memprogram BASIC. Beberapa game ditulis dalam bahasa BASIC, demikian juga banyak aplikasi sederhana ditulis dalam BASIC. Beberapa aplikasi dalam berbagai bank masih ditulis dengan Visual Basic 6. Meski demikian, jika Anda pemula dan baru mulai belajar pemrograman sebaiknya belajar bahasa lain saja, seperti Python atau PHP.

Belajar bahasa BASIC bisa dipelajari sekedar untuk iseng. Bahasanya sederhana, tidak butuh banyak waktu untuk belajar, tidak seperti belajar Rust, Haskell atau Scala. Bisa juga belajar BASIC supaya bisa belajar membuat interpreter atau compilernya.