# Topik 5 Percabangan dan Loop
##### OBJECTIVE
1. Mahasiswa mampu mengetahui dan memahami tentang percabangan dalam assembly.
2. Mahasiswa mampu mengetahui dan memahami tentang looping dalam assembly.
## 5.1 Percabangan
---
### Memodifikasi Alur Instruksi
* CPU secara default mengeksekusi instruksi secara berurutan
* CPU melihat register EIP untuk mengetahui alamat dari instruksi yang akan dieksekusi
* Untuk mengubah alur instruksi, kita perlu mengubah isi EIP
* Kita tidak mengubah langsung, namun menggunakan instruksi-instruksi yang tersedia untuk percabangan
* Dua tipe percabangan:
```
Percabangan tidak berkondisi (uncondisional):
Alur program berpindah ke suatu alamat instruksi tanpa kondisi
```
```
Percabangan Berkondisi (conditional):
Alur program berpindah jika suatu kondisi tertentu terpenuhi
(statment if-else pada bahasa high-level)
```
### Percabangan Tidak Berkondisi
* Instruksi JMP digunakan untuk lompat ke suatu label kode
* Sintaks:
```
JMP Destination
```
* Destination berupa label kode yang menjadi tujuan lompatan (ingat: label kode hanyalah referensi ke alamat instruksi)
* Instruksi JMP mengubah isi dari instruction pointer (EIP) dengan alamat dari label kode.
Contoh:
```python
mov eax, [data]
add eax, ebx
jmp here
sub al, bl
movsx ax, al
here:
call print_int
```
Instruksi sub dan movsx pada contoh diatas tidak akan pernah dieksekusi.
Contoh Instruksi JMP
```
mov ax, 00
mov bx, 00
mov cx, 01
L20:
add ax, 01
add bx, ax
shl cx, 1
jmp L20
```
Contoh diatas adalah loop yang tidak akan pernah berakhir (infinite loop).
### Percabangan Bekondisi
* Untuk melakukan percabangan kondisi, umumnya kita membantuk kondisi dengan dua instruksi: instruksi perbandingan dan intruksi lompat kondisional.
* Salah satu instruksi perbandingan: instruksi cmp (compare).
* Instruksi-instruksi untuk lompat kondisional: instruksi Jxx dimana xx adalah variasi dari instruksi lompat berdasarkan hasil instruksi CMP.
#### Instruksi CMP
* Intruksi CMP (compare) membandingkan nilai dari dua operand dan men-set register EFLAG berdasarkan hasilnya.
* Sintaks:
```
CMP a, b
```
* Intruksi CMP bekerja mirip seperti instruksi SUB yaitu menghitung a-b namun tidak menyimpan hasilnya.
* Sama seperti instruksi SUB, instruksi CMP men-set nilai-nilai EFLAGS berdasarkan hasil pengurangan:
```
Komparasi antar dua bilangan tidak bertanda: ZF (Zero Flag) dan CF (Carry Flag).
Komparasi antar dua bilangan bertanda: ZF (Zero Flag), SF (Sign Flag),
dan OF (Overflow Flag)
```
* Nilai-nilai flag yang diset oleh cmp digunakan oleh instruksi lompat kondisional.
### Instruksi Jxx
<img src = "https://cdn.discordapp.com/attachments/698185008929832960/1006395695265230968/unknown.png"
style = "display : block;
margin-left : auto ;
margin-right : auto ; "/>
* Lompat berdasarkan hasil dari instruksi CMP
* Sintaks:
```
Jxx Destination
```
xx adalah varian sesuai tabel.
Contoh Percabangan Berkondisi
```
Pseudocode
if (EAX == 0) kondisi cmp eax, 0 Komparasi
je thennblock
jne elsebock Instruksi Jxx
EBX =1 block "then" thenblock:
mov ebx, 1 Block "then"
jmp endif
else
EBX = 2; block "else" elseblock:
mov ebx, 2 Block "else"
jmp endif
```
#### Struktur if-then
> Pseudocode
```
if (condition) then
then_block;
```
> Assembly:
```
; instruksi untuk men-set flag (spt. cmp …)
...
jxx endif ; xx sehingga lompat dilakukan
; jika kondisi tidak terpenuhi
; kode untuk block then
...
endif:
```
#### Struktur if-then-else
> Pseudocode
```
if (condition) then
then_block;
else
else_block;
```
> Assembly
```
; instruksi untuk men-set flag (spt. cmp …)
...
jxx else_block ; xx sehingga lompat dilakukan
; jika kondisi tidak terpenuhi
; kode untuk block then
...
jmp endif
else_block:
; kode untuk block else
...
endif:
```
### Jxx Berdasarkan Nilai EFLAGS
Terdapat instruksi Jxx yang lebih generik: lompat dilakukan berdasarkan nilai flag yang ter-set.
| Mnemonic | Keterangan | Bercabang Jika |
| -------- | -------- | -------- |
| JZ | Jump if Zero | ZF = 1 |
| JNZ | Jump if Not Zero | ZF =0|
| JO | Jump if Overflow | OF =1 |
| JNO | Jump if Not Overflow | OF = 0|
| JS | Jump if Signed | SF = 1 |
| JNS |Jump if Not Signed | SF = 0 |
| JC | Jump if Carry | CF = 1 |
| JNC | Jump if Not Carry | CF = 0 |
| JP | Jump if Parity | PF = 1 |
| JNP | Jump if Not Parity | PF = 0 |
Contoh Jxx Generik
Penjumlahan dua bilangan 8-bit, tampilkan pesan overflow jika hasil penjumlahan melebihi 8-bit dan tampilkan hasil jika tidak overflow.
```
.segment data
bil_1 db 255
bil_2 db 1
pesan_of db “Hasil penjumlahan overflow!”, 0
.segment text
mov al, [bil_1]
add al, [bil_2]
jc else_block ; jika tidak overflow ke block else
; Pada penjumlahan tidak bertanda overflow
; ditandai dengan flag carry yang ter-set
; sehingga kita gunakan jc (jump if carry)
; kode untuk block then
movzx eax, al ; zero extend al ke eax
call print_int
jmp endif
else_block:
; kode untuk block else
mov eax, pesan_of
call print_string
endif:
```
## 5.2 Loop
### For Loop
Misal:
sum = 0;
for (i = 0; i <= 10; i++)
sum += i;
```
mov eax, 0 ; eax sebagai sum
mov ebx, 0 ; ebx sebagai i
loop_start:
cmp ebx, 10 ; bandingkan i dengan 10
jg loop_end ; jika (i>10) ke loop_end
add eax, ebx ; sum += i
inc ebx ; i++
jmp loop_start ; lompat ke loop_start
loop_end:
```
### While Loop
while (condition) {
body
```
while:
; instruksi yang men-set flag (spt. cmp, ...)
...
jxx end_while ; bercabang jika
; kondisi = false
; body dari loop
...
jmp while
end_while:
```
### Do While Loop
do {
body
} while (condition)
```
do:
; body dari loop
...
; instruksi yang men-set flag (spt. cmp, ...)
...
jxx do ; bercabang jika
; kondisi = true
```
## Demo
### Demo while loop
sum = 0;
i = 0;
while (i <= 10) {
sum += i;
i++;
}
```
mov eax, 0 ; simpan sum dalam eax
mov ebx, 0 ; ebx sebagai i
while:
; instruksi yang men-set flag (spt. cmp, ...)
cmp ebx, 10 ; ebx ? 10
jg end_while ; bercabang jika ebx > 10
; body dari loop
add eax, ebx ; sum = sum + i
inc ebx ; i++
jmp while
end_while:
call print_int ; print nilai sum pada eax
```
### Demo do while loop
sum = 0;
i = 0;
do {
sum += i;
i++;
} while (i <= 10)
```
mov eax, 0 ; simpan sum dalam eax
mov ebx, 0 ; ebx sebagai i
do:
; body dari loop
add eax, ebx ; sum = sum + i
inc ebx ; i++
; instruksi yang men-set flag (spt. cmp, ...)
cmp ebx, 10 ; ebx ? 10
jle do ; bercabang jika ebx <= 10
```
## Intruksi Loop
Terdapat instruksi khusus untuk melakukan loop: salah satunya adalah instruksi loop.
Sintaks:
```
loop <label>
```
Instruksi loop melakukan:
* Dekrementasi ECX (sehingga ECX harus menjadi indeks dari loop)
* Jika (ECX != 0), bercabang ke label
Contoh Instruksi Loop
Kita ingin menerjemahkan kode berikut ke kode assembly menggunakan
instruksi loop:
```
sum = 0;
for (i = 0; i <= 10; i++)
sum += i;
```
Instruksi loop mengharuskan:
* Indeks dari loop disimpan dalam ECX
* Indeks di-dekrementasi
* Loop keluar ketika indeks sama dengan nol
Sehingga, kita harus mengubah kode di atas menjadi kode berikut:
```
sum = 0;
for (i = 10; i > 0; i--)
sum += i;
```
Contoh:
sum = 0;
for (i = 10; i > 0; i--)
sum += i;
```
mov eax, 0 ; eax sebagai sum
mov ecx, 10 ; ebx sebagai i
loop_start:
add eax, ecx ; sum += i
loop loop_start ; jika i > 0 maka
; pergi ke loop_start
```