# 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
```