Assembly - Instruksi Aritmatika serta Basic Debugging

Instruksi Aritmatika serta basic debugging

Di bab ini kita akan belajar membuat Instuksi Aritmatika, dan juga men-debug-nya menggunakan GDB.

Aritmatika dalam komputer

Jadi aritmatika dalam assembly adalah sebuah instruksi yang di eksekusi melalui Arithmetic Logical Unit (ALU) pada CPU. Seperti matematika pada umumnya, aritmatika di assembly memiliki fungsi yang sama, yaitu pertambahan, pengurangan, perkalian, dan seterusnya.

Tipe Aritmatika

Berikut merupakan jenis-jenis aritmatika yang bisa kita gunakan di assembly. | Tipe Aritmatika | Assembly | Notation | | ————— | ——– |———-| | Addition | add | + | | Subtraction | sub | - | | Multiplication| mul/imul | x | | Division | div/idiv | / | | Increment | inc | +1 | | Decrement | dec | -1 |

Default ukuran semua operasi di atas adalah 32 bit.

Dikarenakan x86 ini bertipe CISC, saya menyederhanakan cara penggunaannya ke yang paling mudah

Addition/Substraction

Addition di assembly mengambil 2 input dan menggabungkannya menjadi satu. Sedangkan substraction mengurangi input pertama dengan input kedua. Bedanya disini kita memiliki source dan destination, dimana source ini akan ditambahkan pada destination address yang dituju.

add <dest>, <src>
sub <dest>, <src>

contoh:

xor eax, eax    ; eax = 0
add eax, 100    ; eax += 100
sub eax, 10     ; eax -= 10

Instruksi diatas akan mengubah eax menjadi 90.

Multiplication

Ada dua macam instruksi, mul untuk unsigned dan imul untuk signed.

mul/imul <src>

Untuk ukuran operan:

  • 8 bit, mengalikan sumber dengan al menghasilkan 8 bit al.
  • 16 bit, mengalikan ax, menghasilkan 32 bit dx:ax, 16 bit atas dan 16 bit bawah.
  • 32 bit, mengalikan eax, menghasilkan 64 bit, edx:eax, 32 bit atas dan 32 bit bawah.
  • 64 bit, mengalikan rax, menghasilkan 128 bit, rdx:rax, 64 bit atas dan 64 bit bawah.
Ukuran Dest Hasil
8 bit ah al
16 bit ax dx:ax
32 bit eax edx:eax
64 bit rax rdx:rax

contoh:

mov eax, 2      ; eax = 2
mov edi, 4      ; edi = 4
imul edi        ; edx:eax = eax * edi

Maka nilai eax akan menjadi 8, dan nilai edx menjadi 0.

Division

Seperti perkalian, idiv untuk signed dan div untuk unsigned.

div/idiv <src>

Untuk ukuran sumber:

  • 8 bit, ax dibagikan dengan sumber, menyimpan hasilnya di al, sisa pembagian di ah.
  • 16 bit, dx:ax 32 bit dibagikan , menyimpan hasil di ax, sisanya di dx.
  • 32 bit, edx:eax 64 bit dibagikan, menyimpan hasil di eax, sisanya di edx.
  • 64 bit, rdx:rax 128 bit dibagi, menyimpan hasil di rax, sisanya di rdx.


Ukuran Numerator Hasil Sisa
8 bit ax al ah
16 bit dx:ax ax dx
32 bit edx:eax eax edx
64 bit rdx:rax rax rdx


Tidak seperti imul/mul, idiv/div membutuhkan instruksi khusus.

Untuk div, jika kita hanya ingin membagi dengan nilai 16 bit, 32 bit, atau 64 bit.

nilai ax, edx, atau rdx harus 0. kecuali jika ingin nilai yang dibagi sebesar 2 kali lipat ukuran tersbut.

Serta idiv, nilai ax, eax, atau rax harus dibikin sign-extend ke dalam gabungan 2 register.

  • cwd (convert word to dword) untuk ax, dx:ax = (signed)ax
  • cdq (convert dword to qword) untuk eax, edx:eax = (signed)eax
  • cqo (convert qword to oword) untuk rax, rdx:rax = (signed)rax

contoh:

mov eax, 100    ; eax = 100
cdq             ; edx:eax = (signed)eax
mov edi, 10     ; edi = 10
idiv edi        ; edx = edx:eax % edi
                ; eax = edx:eax / edi

Nilai eax adalah 10, dan edx adalah 0.

xor edx, edx    ; edx = 0
mov eax, 4      ; eax = 4
mov edi, 10     ; edi = 10
div edi         ; edx = edx:eax % edi
                ; eax = edx:eax / edi  

Maka nilai eax akan menjadi 0, dan nilai edx menjadi 4.

Increment/Decrement

Increment dalam assembly berfungsi untuk menambah nilai dari destinasi sebanyak 1. Sedangkan decrement mengurangi nilai dari destinasi sebanyak 1.

inc <dest>
dec <dest>

contoh:

xor eax, eax  ; eax = 0
inc eax       ; eax += 1
inc eax       ; eax += 1

Maka hasilnya adalah 2.

mov eax, 10 ; eax = 10
dec eax     ; eax -= 1
dec eax     ; eax -= 1

maka hasilnya adalah 8.

Perhatian! instruksi inc dan dec tidak disarankan untuk digunakan karena bisa menyebabkan partial register flags stall. Serta dalam CPU Modern, add dan sub lebih cepat dibandingkan inc dan dec

Debugging di GDB

Basic Command

| Perintah | Fungsi | Penggunaan | | ————— | ——– | ———- | | help | Menampilkan opsi pada suatu perintah| help <argument(optional)> | | run | Menjalankan program | run <argument(optional)> | | disass | Mendisassamble | disass <symbol atau pointer>| | set | Setting variable konfigurasi pada gdb| set <argument> <value> | | break | Set breakpoint| break <symbol atau *address> | | next | Lanjut ke instruksi selanjutnya| next | | continue | Melanjutkan program setelah breakpoint | continue| | info | Menampilkan informasi| info <argument> | | commands | Membuat auto script saat menginjak breakpoint | commands <range of breakpoint, example: 1-4, 2> |

Example:

Men-disassamble dan menganalisis instruksi yang sedang dieksekusi

Kita akan menggunakan instruksi dibawah, sebagai uji coba.

section .text
        global _start
_start:
        xor eax, eax ; eax = 0
        add eax, 10 ; eax += 10
        add eax, 20 ; eax += 20
        add eax, 30 ; eax += 30

exit:
        mov eax, 60 ; exit syscall
        xor edi, edi; edi = 0
        syscall

Setelah kita meng-compile instruksi diatas, kita akan menganalisa bagaimana fungsi add bekerja menggunakan GDB.

  • Pertama kita akan menjalankan gdb, dengan menggunakan perintah gdb <nama_program>
  • Setelah masuk kedalam Command Line Interface di GDB, kita akan mengetikkan perintah set disassembly-flavor intel untuk mengubah format disassembly-nya menjadi format intel, agar lebih mudah dibaca.
  • Lalu kita akan set step-mode variable menjadi on, agar kita dapat mendebug instruksi assembly satu persatu, set step-mode on.

Ok, setelah men-setup GDB-nya, kita langsung saja ke bagian utama, yaitu menganalisa instruksi add pada program.

  • Pertama kita akan set breakpoint pada symbol _start, break _start
  • Next, kita jalankan programnya, run.
  • Ketik next untuk masuk ke instruksi berikutnya.
  • Kita akan meliahat registernya, dan ingat disini value rax masih 0, info registers. output:

  • Kita next lagi.
  • Lalu lihat registernya, info register. Maka valuenya akan berubah, seperti dibawah

Kenapa bisa berubah? yup, karena kita baru saja melewati instruksi add eax, 10

  • Ketik disasss _start

output:

Bisa dilihat diatas, saat kita men-disassemble symbol _start, anak panah menuju ke instruki ke-3, yang artinya instruksi ke-2 telah selesai di eksekusi, dan alhasil menambahkan 0xa atau 10 ke rax.

Membuat script automasi yang berjalan saat menginjak breakpoint.

section .text
        global _start
_start:
        mov eax, 2
        mov ebx, 4
        mul ebx   
        mov ebx, 4
        mul ebx   

exit:
        mov eax, 60 
        xor edi, edi
        syscall
  • Pertama kita set dulu breakpointnya, contoh:

image

Disini saya menyetel breakpoint pada symbol _start instruksi pertama, kedua, dan ketiga. Untuk mendapatkan address dari suatu instruksi, kalian bisa menggunakan disass.

  • Lalu ketikkan perintah commands, dan tentukan breakpoint mana saja yang mau kita buat skrip automasi.

    Note: Untuk melihat list breakpoint kalian bisa menggunakan perintah info breakpoints image

image

  • Setelah itu kalian bisa mengetikkan skrip yang nantinya akan dieksekusi saat breakpoint. contoh:

image

  • Saat kita run, dan menginjak breakpoint maka ama muncul output dari script yang kita buat tadi.

asd

image

image

results matching ""

    No results matching ""