Mengenal dan memakai instruksi SIMD

Instruksi SIMD (Single Instruction Multiple Data) adalah jenis instruksi pada prosesor modern yang bisa melakukan operasi terhadap banyak data sekaligus (biasanya bentuknya adalah array/vector). Instruksi assembly dalam sebuah ISA biasanya hanya melakukan hal dasar berikut:

  • Menyalin data dari memori/register ke memori/register
  • Melakukan operasi terhadap satu atau lebih register dan menyimpan hasilnya di memori atau register (contoh: penjumlahan, perkalian, operasi bit, dsb). Beberapa operasi akan mempengaruhi flag pada CPU.
  • Memindahkan alur eksekusi ke alamat tertentu dalam kondisi tertentu (biasanya berdasarkan flag)
  • Melakukan manipulasi hardware spesifik (misalnya mengakses I/O, enable interrupt, enable paging, dsb)

Instruksi SIMD bisa melakukan load/save register dari/ke memori, melakukan manipulasi pada register, tapi satu instruksi bisa memproses banyak data sekaligus. Jika dilakukan dengan benar, ini bisa mempercepat program cukup signifikan. Instruksi SIMD tidak bisa melakukan branching ke banyak alamat sekaligus.

Sejarah SIMD ini cukup panjang: singkatnya tahun 1970an sudah dipikirkan ide ini dan sudah diimplementasikan di berbagai komputer besar, tapi baru masuk ke CPU untuk consumer di akhir abad lalu. Data yang diproses semuanya perlu berurutan (seperti array) dan biasanya disebut sebagai vector (tidak berhubungan dengan istilah vektor di matematika).

Lanjutkan membaca Mengenal dan memakai instruksi SIMD

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.

Lanjutkan membaca Assembler di browser berbasis Keystone dengan WebAssembly

Mendalami Bahasa C

Saya memberikan saran agar seseorang “mendalami bahasa C” jika ingin belajar reverse engineering. Ada pertanyaan menarik yang diajukan ke saya: sedalam apa belajarnya pak? apa yang harus dipelajari. Sesuai KBBI mendalami di sini berarti: meresapi; menyelami; mempelajari (menelaah, menyelidiki) dalam-dalam.

Saya tidak akan membahas dalam mengenai kenapa seseorang perlu memahami bahasa C, singkatnya: saat ini C masih dipakai di mana-mana, dan akan terus begitu untuk beberapa belas/puluh tahun mendatang. Kernel berbagai sistem operasi ditulis dalam C, berbagai library penting masih ditulis dalam C (library kompresi, enkripsi, image encoding/decoding, dsb), dan bahkan kebanyakan bahasa pemrograman lain diimplementasikan dalam C (misalnya Ruby, Python, dan PHP).

Di awal, pelajarilah dan pahamilah semua konsep dasar dalam bahasa C. Ini seharusnya tidak makan waktu lama. Bahasa C hanya punya beberapa tipe data dasar (void, char, short, int, long, float, dan double) masing-masing bisa signed atau unsigned. Kita bisa mendefinisikan sebuah konstanta dengan const. Tipe data lain adalah enum, union, dan struct (sudah pernah saya bahas di sini) semua tipe data bisa diberi nama dengan typedef.

Lanjutkan membaca Mendalami Bahasa C

Signature email jaman kuliah

Dulu waktu kuliah, saya punya signature email seperti ini:

main(i){putchar((i-1)["Xme]i_l"]+(i++))&&(8-i)&&main(i);}


Ternyata masih ada beberapa orang yang ingat, dan masih banyak yang penasaran apa artinya (cuma satu kata: Yohanes) danĀ  kok bisa muncul seperti itu?

Lanjutkan membaca Signature email jaman kuliah

Memahami Static dan Shared Library di Linux

Saya masih sering melihat programmer C dan juga administrator yang bingung dengan konsep shared library. Shared library adalah file berisi kode yang bisa diload saat program dieksekusi (runtime). Karena diload pada runtime, maka sebuah shared library bisa digunakan oleh lebih dari satu program.

Penjelasan mengenai static dan shared library biasanya membingungkan, jadi di posting ini saya akan menjelaskan dengan banyak contoh. Sebenarnya hampir semua contoh di tulisan ini berlaku juga untuk lingkungan POSIX lain selain Linux, tapi saya hanya mencoba kode ini di Linux 64 bit dengan compiler gcc. Di balik layar, program gcc sebenarnya akan memanggil berbagai program lain (preprocessor, assembler, linker) tergantung pada parameter yang kita berikan tapi agar penjelasannya sederhana, saya akan memakai gcc saja dan tidak akan menjelaskan apa yang terjadi di balik layar.

Kode monolitik

Kita mulai dari kode yang sangat sederhana seperti ini:

/*file: main.c */
#include <stdio.h>

double operation(double a, double b)
{
  printf("Plus operation\n");
  return a+b;
}

int main(int argc, char *argv[])
{
  double a = 5;
  double b = 3;
  printf("Result of operation (%.2f, %.2f) is: %.2f\n", a, b, operation(a, b));
  return 0;
}

Karena semua sudah ada di satu file, maka ini bisa dikompilasi dan jalankan langsung.

gcc main.c -o main

Memecah source code

Di sini ada satu fungsi bernama operation yang hanya melakukan operasi sangat sederhana. Anggap saja fungsi ini rumit dan penting dan ingin kita pisahan agar bisa dipakai oleh orang lain. Sekarang operation saya pindahkan ke operation.c

Lanjutkan membaca Memahami Static dan Shared Library di Linux

System programming

Banyak orang yang terkesima dengan orang yang memprogram di level kernel sistem operasi; banyak juga yang menganggap wilayah kompilasi atau interpretasi itu sesuatu yang rumit, dan sebaiknya diterima saja, tidak perlu dipelajari.

Sebagian orang bersifat tidak mau tahu. Misalnya ada yang bilang: mengapa belajar assembly atau C/C++, bahasanya nggak dipakai, mendingan belajar PHP, Ruby, Java atau .NET. Orang-orang tersebut tidak menyadari bahwa compiler dan atau runtime bahasa-bahasa tersebut dibuat dengan C dan C++. Sebagian besar library yang dipakai di berbagai bahasa juga diimplementasikan di C/C++.

Sebagian kemampuan prosessor juga tidak akan bisa dimanfaatkan secara maksimal oleh bahasa tingkat tinggi, tanpa bantuin assembly dan atau C/C++. Contoh terbaru adalah instruksi-instruksi STTNI (String & Text New Instructions) yang diperkernalkan di prosessor baru Intel dengan arsitektur Nehalem untuk mempercepat pemrosesan teks (dan parsing XML) tidak akan bisa dilakukan.

Bahkan jika Anda tidak memprogram dalam bahasa C sekalipun, pengetahuan tersebut bisa berguna, misalnya Anda bisa mengoptimasi penggunaan memori dan mengoptimasi kecepatan di PHP. Lihat juga posting saya mengenai Kritik PHP.

Sekarang pertanyaan berikutnya yang mungkin muncul adalah: bagaimana saya belajar pemrograman sistem?


System programming adalah aktivitas pembuatan software sistem. Ini cakupannya luas, dari mulai kernel sistem operasi, sampai compiler, dan aneka utility level sistem.

Lanjutkan membaca System programming

Struct vs Union

Posting ini merupakan jawaban saya pada sebuah pertanyaan di milis linux-programming (Juli 2007). Saya posting di sini karena mungkin akan berguna bagi pemula dalam C.

Struct berguna untuk mengelompokkan data. Contoh: struktur mahasiswa mungkin memiliki NIM, nama, dst. Rasanya ini mudah dimengerti.

Union: untuk memberi beberapa nama untuk satu lokasi memori. Ini yang biasanya yang sulit dimengerti oleh yang baru belajar C. Saya berikan beberapa contoh:

#include <stdio.h>

union {
int a;
int b;
} a_dan_b;

int main()
{
a_dan_b.a = 5;
printf("%d\n", a_dan_b.b);
return 0;
}

Apa hasil keluaran program itu? Jawabnya adalah 5, karena a dan b menempati lokasi memori yang sama. Kita bisa menambahkan banyak variabel di union. Jika tipe variabel itu sama, maka nilainya akan sama. Kita bisa membuat union dari tipe yang berbeda juga, misalnya:

Lanjutkan membaca Struct vs Union