Oleh: Reza Ervani bin Asmanu
Dalam pemrograman bahasa rakitan (assembly), kode yang kita tulis tidak sepenuhnya terdiri dari instruksi yang dieksekusi oleh prosesor (CPU). Terdapat kategori perintah khusus yang ditujukan bukan untuk perangkat keras, melainkan untuk perangkat lunak penerjemah itu sendiri (Assembler). Perintah-perintah ini dikenal sebagai Assembler Directives atau Pseudo-operations.
Pada berkas boot.S yang kita gunakan untuk inisialisasi Raspberry Pi, terdapat dua directive krusial yang diawali dengan tanda titik (.), yaitu .section dan .global. Artikel ini akan membahas fungsi teknis dan implikasi arsitektural dari kedua directive tersebut dalam lingkungan GNU Assembler (GAS).
1. Definisi Assembler Directives
Assembler Directives adalah perintah administratif yang mengontrol proses perakitan kode. Jika instruksi mesin (seperti MOV, ADD, BL) diterjemahkan secara langsung menjadi kode biner untuk dieksekusi CPU, maka directives berfungsi untuk mengatur tata letak memori, visibilitas simbol, dan struktur berkas objek (.o) yang dihasilkan.
CPU tidak pernah “melihat” directives ini. Mereka dieksekusi dan diselesaikan pada saat kompilasi (compile-time), bukan saat eksekusi (run-time).
2. Analisis Directive .section
Salah satu tugas utama seorang pengembang OS adalah manajemen memori (Memory Layout). Di sinilah directive .section memegang peranan vital.
Sintaks
.section ".text.boot"
Penjelasan Teknis
Dalam format berkas ELF (Executable and Linkable Format), program dibagi menjadi beberapa segmen logis yang disebut Section. Beberapa section standar meliputi:
.text: Berisi kode program (instruksi mesin) yang bersifat read-only..data: Berisi variabel global yang telah diinisialisasi..bss: Berisi variabel yang belum diinisialisasi (dialokasikan saat runtime).
Implementasi pada Raspberry Pi
Pada baris kode di atas, kita mendefinisikan sebuah section kustom bernama .text.boot. Kita tidak menggunakan section standar .text secara langsung karena kita memiliki kebutuhan spesifik terkait urutan booting.
- Grouping (Pengelompokan): Directive ini memerintahkan assembler untuk menempatkan seluruh kode di bawahnya ke dalam wadah bernama
.text.boot. - Linking Control (Kendali Tautan): Nama
.text.bootini menjadi referensi bagi Linker (melalui skriplinker.ld).
Dalam skrip linker.ld, kita menginstruksikan Linker untuk mengambil section .text.boot ini dan meletakkannya tepat di alamat memori 0x8000.
Mengapa ini krusial? Karena bootloader bawaan Raspberry Pi (GPU Firmware) diprogram secara keras (hardcoded) untuk melompat ke alamat fisik 0x8000 saat menyalakan CPU ARM. Dengan memisahkan kode ini ke dalam section khusus .text.boot, kita menjamin bahwa instruksi pertama yang ditemui CPU adalah kode inisialisasi kita, bukan kode fungsi lain yang mungkin teracak posisinya.
3. Analisis Directive .global
Dalam proyek perangkat lunak yang kompleks, kode seringkali dipecah menjadi beberapa berkas (modular). Directive .global mengatur visibilitas simbol antar-modul tersebut.
Sintaks
.global _start
Penjelasan Teknis
Secara default, label atau simbol (seperti _start:, loop:, atau halt:) yang didefinisikan dalam assembly bersifat Lokal. Artinya, simbol tersebut hanya dikenali di dalam berkas tempat ia ditulis dan tidak terlihat oleh berkas lain atau oleh Linker.
Directive .global mengubah atribut simbol tersebut menjadi Global (External Linkage).
Peran dalam Entry Point
Pada kasus _start:
- Simbol Eksternal: Dengan mendeklarasikan
.global _start, kita memberitahu Assembler untuk mencatat_startdalam tabel simbol (symbol table) berkas objek sebagai simbol yang bisa diakses dari luar. - Referensi Linker: Linker (
ld) membutuhkan titik masuk (entry point) untuk mengetahui di mana eksekusi program dimulai. Secara konvensi standar GNU, titik masuk ini diberi nama_start. - Resolusi Alamat: Jika kita memiliki berkas C yang ingin memanggil fungsi assembly, atau sebaliknya, simbol-simbol tersebut wajib dideklarasikan sebagai
.global. Tanpa directive ini, Linker akan mengeluarkan pesan kesalahan “undefined reference” karena ia tidak dapat menemukan alamat dari label tersebut.
Kesimpulan
Kedua directive di atas bekerja secara sinergis untuk membentuk fondasi eksekusi program:
.section ".text.boot"memastikan lokasi fisik kode berada di tempat yang benar (0x8000) agar bisa ditemukan oleh hardware/bootloader..global _startmemastikan alamat logika kode dapat ditemukan dan dikelola oleh software (Linker) sebagai pintu masuk program.
Tanpa pemahaman yang tepat mengenai directives ini, kode assembly yang valid sekalipun tidak akan dapat berjalan karena gagal ditempatkan pada struktur memori yang dipersyaratkan oleh sistem.
