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