# Bab 2. Pengenalan ke Program Assembly (NASM) **OBJEKTIF:** 1. Mahasiswa mampu mengetahui tentang Arsitektur x86 2. Mahasiswa mampu mengetaui tentang Assembler dan Linker 3. Mahasiswa mampu menulis program Hello World dalam Bahasa Assembly 4. Mahasiswa mampu memahami serta mengetahui tentang struktur program NASM --- ## 2.1 Arsitektur x86 Untuk mempelajari Bahasa assembly kita perlumemilih satu keluarga prosesor, karena instruksiinstruksi assembly berbeda untuk keluarga prosesor yang berbeda Kita menggunakan bahasa assembly untuk keluarga prosesor 32-bit Intel 80x86 (x86 singkatnya) Untuk menulis program assembly kita perlu memahami: Register-register yang tersedia Instruction Set Architecture (ISA) Register adalah tempat penyimpanan sementara dalam prosesor Terdapat banyak register pada x86, namun untuk pemrograman dasar assembly, kita hanya memerlukan register dalam tiga kategori berikut: - General Purpose Register: Terdiri dari 8 register 32-bit Digunakan untuk tempat penyimpanan sementara sebelum operasi aritmatika, operasi bit, dsb. - Intruction Pointer: Satu register 32-bit: EIP (Extended Instruction Pointer) Menyimpan alamat memori dari instruksi berikutnya yang akan dieksekusi Nilainya dapat kita manipulasi untuk mengubah alur program (percabangan) - Register EFLAGS: Satu register 32-bit: EFLAGS (Extended Flags) Setiap bit-nya mempunyai arti tertentu Digunakan untuk melihat status hasil aritmatika dan perbandingan ### 2.1.1 General Purpose Register Terdapat beberapa ketentuan instruksi mov, antara lain: > * Terdapat 8 register 32-bit: EAX, EBX, ECX, EDX, ESI, EDI, EBP, dan ESP > * EAX, EBX, ECX, dan EDX dapat digunakan 16 bit terendahnya: AX, BX,CX, DX > * AX, BX, CX, dan DX dapat digunakan: `8 bit terendahnya: AL, BL, CL, DL` `8 bit tertingginya: AH, BH, CH, DH` > * ESI, EDI, EBP, dan ESP dapat digunakan 16 bit terendahnya: SI, DI, BP, SP > * ESP (Extended Stack Pointer) dan EBP (Extended Base Pointer) mempunyai kegunaan khusus saat menggunakan stack ### 2.1.2 Register EFLAG * Carry Flag (CF) – menandakan hasil operasi aritmatika bilangan tidak bertanda melebihi jangkauan ukuran bit tujuan (bernilai 1 jika ya) * Overflow Flag (OF) – menandakan hasil operasi aritmatika bilangan bertanda melebihi jangkauan ukuran bit tujuan (bernilai 1 jika ya) * Sign Flag (SF) – menandakan jika hasil operasi aritmatika menghasilkan nilai negatif (bernilai 1 jika ya) * Zero Flag (ZF) – menandakan jika hasil operasi aritmatika menghasilkan nilai nol (bernilai 1 jika ya) * Auxiliary Carry Flag (AF) – menandakan jika hasil operasi aritmatika menyebabkan sebuah bit carry dari bit 3 ke bit 4 dalam operand 8 bit (bernilai 1 jika ya) # ISA x86 Spesifikasi ISA untuk Intel x86 dapat dilihat di http://ref.x86asm.net/ ### 2.2 Assembler dan Linker Bahasa Assembly adalah bahasa pemograman low-level karena paling dekat dengan kode mesin (bahasa yang dimengerti komputer) Satu statemen pada bahasa assembly diterjemahkan menjadi satu baris statemen kode mesin Bahasa assembly lebih sulit dipelajari karena: ``` Tidak menggunakan bahasa yang mudah dibaca Statemen atau perintah berupa instruksi operasi CPU ``` ### 2.2.1 Bahasa Assembly x86 v. Bahasa High Level Misalkan, kita menuliskan statemen program yang menambahkan dua variabel a dan b dan simpan hasilnya ke variabel x: > Dalam bahasa high-level kita dapat menuliskannya: ``` x = a+ b ``` > Dalam bahasa assembly, satu statemen tersebut dituliskan dalam tiga baris ``` MOV eax, [a] ADD eax, [b] MOV x, eax ``` > Pada baris pertama kita melakukan ambil data yang disimpan dalam alamat memori a, dan pindahkan(move) ke register eax. > kemudian mengambil data yang disimpan dala alamat memoru b, dan tambahkan(add) ke regites eax > dan baris terakhir yaitu mengambil data dari register eax, dan pindahkan ke alaamt memori x ### 2.2.2 Kompilasi bahasa high level > Bahasa High-Level seperti C, C++, atau Java merupakan abstraksi dari Bahasa Assembly > Kode program dalam bahasa High-Level dikompilasi menjadi bahasa assembly terlebih dahulu sebelum dapat dijalankan ### 2.2.3 Kode Assembly dan Kode Mesin * Kode Assembly | ADD | eax, [b] | > Proses Assembly: > Menerjemahkan kode assembly menjadi kode mesin * Kode Mesin | 11000011 | 011101010101011| * Kode Mesin (dalam heksadesimal) | C3 | c9 | Proses Assembly: Proses Link: Menerjemahkan Bahasa Assembly Menggabungkan file object dengan menjadi Kode Mesin file object lain seperti file object dari OS Input: Input: Kode assembly dalam file teks File-file object dengan ekstensi .asm dengan ekstensi .asm Output: Output: Kode mesin dalam file object Program executable, file dengan dengan ekstensi .obj (Windows) ekstensi .exe (Windows) ### 2.2.4 Assembler > Assembler menerjemahkan kode assembly menjadi kode mesin > Kode assembly tidak portable  tidak bisa digunakan di arsitektur CPU yang berbed > Terdapat beberapa assembler untuk arsitektur x86: MASM (Microsoft Macro Assembler), Turbo Assembler, FASM (Flat Assembler), NASM (Netwide Assembler), dsb. > Kita menggunakan Netwide Assembler (NASM) ### 2.2.5 Editor, Assembler dan Linker > Untuk membuat program assembly dan menjalankannya kita memerlukan: * Editor Kita dapat menggunakan editor apa saja, karena file assembly hanyalah file teks. Disini kita akan menggunakan Notepad++ yang sudah terdapat syntax highlight Download Notepad++ di: https://notepad-plus-plus.org/ * Assembler Kita menggunakan NASM untuk assembler Download NASM di: https://www.nasm.us/ * Linker Kita menggunakan C compiler sebagai linker Download NASM di: https://www.nasm.us/ ### 2.3 Menulis Helloword dalam bahasa assembly #### Code Program Area untuk menyertakan file ekternal dengan directive %include ```python ; directive include %include "asm_io.inc" ``` Segment data – tempat mendeklarasikan variable terinisialisasi (dengan nilai awal) ```python segment .data ; directive Dx hello db "Hello, World!",0 ``` segment bss – tempat mendeklarasikan variable tidak terinisialisasi (tanpa nilai awal) ```python segment .bss ; directive RESx ``` segment text – tempat menuliskan kode program ```python segment .text global _main _main: ; Routine “setup” enter 0, 0 pusha ; Instruksi-instruksi mov eax, hello ; pindahkan alamat hello ke eax call print_string ; panggil fungsi print_string ; Routine “cleanup” popa mov eax, 0 leave ret ``` #### Comment > Bahasa assembly tidak mudah untuk dibaca, penulisan comment sangatlah penting > Comment pada NASM diawali dengan ‘;’ (titik koma) Contoh: ``` add eax, ebx ; y = y + b ``` #### Direcrive Directive adalah perintah ke assembler untuk melakukan sesuatu saat proses assembly namun bukan perintah yang diterjemahkan menjadi instruksi kode mesin. ``` Antara lain: %define dan %include ``` Kita menggunakan directive %define untuk mendefinisikan constant. ``` Misalkan kode kita sering munggunakan angka 100 untuk suatu hal tertentu, misalkan untuk besar ukuran. Kita dapat menuliksan dalam kode NASM : %define SIZE 100 Saat proses assembly, NASM akan mensubtitusi semua kata SIZE dalam program dengan nilai 100 ``` Kita menggunakan directive %include untuk menyertakan macro kode assembly pada file lain ke kode : ``` %include “nama_file.inc” ``` #### Reserved Word Reserved Words adalah kata-kata yang mempunyai arti tertentu dan harus digunakan dalam konteks yang sesuai. Reserved words antara lain: ``` ○ Instruction Mnemonic; seperti: MOV, ADD, dan MUL ○ Nama Register: EAX, EBX, dst. ○ Directive; ○ Specifier: untuk informasi ukuran data dari variable dan operand; contoh: BYTE dan WORD ``` #### "Setup" dan "Clean-up" > Sebelum dan setelah menjalankan instruksi pada program, kita perlu melakukan routine “setup” dan “clean-up”. > Semua kode instruksi yang kita tulis berada setelah routine “setup” dan sebelum routine ”clean-up” #### Input dan Output Menulis program assembly yang menerima input dan mengeluarkan output merupakan hal yang sulit. Kita perlu memahami system call dari sistem operasi (berbeda untuk setiap sistem operasi) Untuk memudahkan, kita akan memanfaatkan dua file: asm_io.inc dan asm_io.asm, yang berisi fungsi-fungsi dan macro-macro yang dapat digunakan untuk input dan output. Kita menyertakan file asm_io.inc pada kode program dengan menuliskan perintah include pada bagian awal kode: ``` %include “asm_io.inc” ``` Kita juga akan menyertakan asm_io.asm pada proses link. #### Fungsi I/O dalam asm_io ``` print_char : print karakter yang sesuai dengan kode ASCII yang disimpan dalam register A ``` ``` print_string : print isi dari string yang disimpan dalam alamat dalam EAX ``` ``` print_nl : print baris baru ``` ``` read_int : membaca sebuah integer dari keyboard dan menyimpannya dalam EAX ``` ``` read_char : membaca sebuah karakter dari keyboard dan menyimpannya dalam AL ``` #### Macr-macro dalam asm_io.inc > dump_regs : print byte-byte yang disimpan dalam register dan juga bitbit dalam register EFLAGS >dump_memory : print byte-byte yang disimpan dalam memori #### Proses Assembly (dengan asm_io) ``` !!!! Pastikan file asm_io.inc, asm_io.asm, dan program assembly Anda dalam satu folder/direktori ``` > Assembly <nama_prog>.asm menjadi <nama_prog>.obj: ``` > nasm –f win32 <nama_prog>.asm ``` > Assembly asm_io.asm menjadi asm_io.obj: ``` > nasm –f win32 asm_io.asm ``` > Link <nama_prog>.obj, dan asm_io.obj: ``` > gcc –m32 –o <nama_program>.exe <nama_prog>.obj asm_io.obj ``` ### 2.4 Struktur Program NASM > segment data – tempat mendeklarasikan variabel terinisialisasi (dengan nilai awal). > segment bss – tempat mendeklarasikan variabel tidak terinisialisasi (tanpa nilai awal) > segment text – tempat menuliskan kode program #### Segment.data ``` label Dx nilai_awal [, nilai_awal, …] ``` Label: • Digunakan sebagai nama variable • Bisa ditentukan apasaja selama tidak sama dengan reserved words • Case sensitive • Penanda (pointer) ke address memori byte pertama dari data • Opsional Directive Dx: perintah assembler untuk besar alokasiruang memori | Directive | Kegunaan | Ruang Memory| | -------- | -------- | ------ | | DB | Define Byte | 1 Byte| | DW | Define Word | 2 Byte| | DD | Define Double Word | 4 Byte| | DQ | Define Quad Word | 8 Byte| | DT | Define Ten Byte | 10 Byte| nilai_awal • Bisa berupa nilai konstan, karakter, atau string • Bisa lebih dari satu (mis. untuk deklarasi array) ``` Nilai konstan Format: (+/-)digit[radiks] Radiks: d: decimal (default) b: biner h: heksadesimal o: octal Contoh: 26, 26d, 11010011b, 42o, 1Ah, 0A3h, 0xFE Note: Angka heksadesimal juga dapat ditulis tanpa radiks h, namun harus diawali dengan 0x. Angka heksadesimal yang diawali dengah huruf harus ditulis dengan awalan 0 ``` > Character/String: ``` o Ditulis dalam tanda kutip tunggal atau kutip ganda o Contoh: ‘A’, “Hello” ``` #### Contoh Deklarasi Variable .data var1 DW 12345 2 byte, bernama var1, di-inisialisasi ke 12345 var2 DB 17o 1 byte, bernama var2, di-inisialisasi ke oktal 17 var3 DB 110101b 1 byte, bernama var3, di-inisialisasi ke biner 110101 bil_neg DW -12345 2 byte, bernama bil_neg, di-inisialisasi ke desimal negatif 12345 L1 DB 2fh 1 byte, bernama L1, di-inisialisasi ke heksadesimal 2FH bil_hex DD 0FFFF1A92h 1 byte, bernama bil_hex, di-inisialisasi ke heksadesimal FFFF1A92 (catatan: heksadesimal yang dimulai dengan huruf harus ditambahkan 0 di depannya #### Dx dengan lebih dari satu nilai awal > L3 DB 0, 1, 2, 3 > `Mendefinisikan 4 bytes, di-inisialisasi ke 0, 1, 2, dan 3` > `L3 adalah pointer ke byte pertama` > L4 DB “w”, “o”, “r”, “d”, 0 > > `Mendefinisikan string null-terminated, di-inisialisasi ke “word\0” ` > ` L4 adalah pointer ke byte awal string` > > L5 DB “word”, 0 > `Ekuivalen dengan di atas, lebih mudah ditulis` #### Dx dengan kualifier times Misal, kita ingin mendeklarasikan 100 bytes yang kesemuanya diinisialisasi ke 0 Kita harus menuliskan: ``` L6 DB 0, 0, 0, …, 0 (0 ditulis sebanyak 100 kali) ``` NASM menyediakan shortcut untuk melakukan ini: kualifier times. Dengan kualifier times: ``` L6 times 100 DB 0 ``` #### Big Endian dan Little Endian Terdapat dua metode pengurutan byte-byte dari data multi-byte dalam memori: 1. Little Endian: digunakan oleh prosesor Intel dan AMD 2. Big Endian: digunakan oleh prosesor IBM #### Segment .bss Perintah deklarasi data tidak terinisialisasi: ``` label RESx kelipatan ``` > label * Digunakan sebagai nama variable * Bisa ditentukan apasaja selama tidak sama dengan reserved words * Case sensitive * Penanda (pointer) ke address memori byte pertama dari data * Opsional > Directive RESx * keyword untuk besar alokasi ruang memori tidak terinisialisasi > Kelipatan * Pengali banyaknya ruang memori dari yang didefinisikan pada RESx * Berupa angka konstan atau ekspresi yang menghasilkan konstan |Directive RESx | Kegunaan | Ruang Memory| | -------- | -------- | ------ | | RESB | Reserve Byte | 1 Byte| | RESW | Reserve Word | 2 Byte| | RESD | Reserve Double Word | 4 Byte| | RESQ | Reserve Quad World| 8 Byte| | REST | Reserve Ten Byte | 10 Byte| Kelipatan: * Pengali ruang memori dari unit yang didefinisikan RESx * Berupa nilai konstan atau ekspresi yang menghasilkan konstan Contoh: ``` temp RESTB 1 Mengalokasikan 1 x 1 byte (= 1 byte) ruang memori dengan nama temp reserve RESW 100 Mengalokasikan 100 x 2 byte (= 200 byte) ruang memori dengan nama reserve ``` #### Segment .text Format sintaks instruksi: ``` label: mnemonic operand [, operand, …] ``` > Label: * Disebut dengan label kode * Opsional * Digunakan sevagai pointer ke alamat memori tampat instruksi * Diperlukan dalam percabangan untuk target lompatan * Dapat dinamakan apa saja selama tidak sama dengan reserve words dan harus diakhiri titik dua (:) > Mnemonic * Keyword untuk instruksi operasi CPU > Operand * Berupa register, alamat/isi memori, ummediate value (nilai langsung) * Bisa lebih dari satu, tergantung dari mnemonic Untuk apa label pada instruksi? * CPU mempunyai instruksi untuk mengubah alur instruksi (untuk percabangan) yaitu JMP * Label #### Operand Jenis operand-operand ``` Register: nama register * ADD eax, ebx bearti eax = eax + ebx ``` ``` Memory: alamat/isi memori * Tanda kurung kotak [] digunakan untuk mereferensi isi memori * MOV eax, [var1] Berarti pindahkan isi memori dari alamat va1 ke register eax. eax = AABBCCDD * MOV ecx, var1 Berarti pindahkan alamat memory var1 ke register ecx; ecx = 000000F1 ``` ``` Immediate Value: nilai langsung berupa angka konstan * ADD eax, 2 berarti eax = eax + 2 ```