Selasa, 15 Januari 2013
  Bagi seseorang yang bergelut di  dunia   security bahasa Assembly adalah bahasa yang wajib dikuasai.  Karena   bahasa ini adalah bahasa tingkat rendah, dekat dengan bahasa  mesin   (biner), maka mempelajari bahasa ini akan sangat menguntungkan.  Dengan   mempelajari bahasa assembly, sedikit banyak secara otomatis kita  akan   memahami cara komputer bekerja lebih dalam lagjuga sebagai pembuka sebelum  saya membahas mengenai shellcode,   buffer overflow dan teknik exploitasi  lain yang membutuhkan pemahaman   mengenai assembly dan sistem operasi.  Bila anda ingin menjadi hacker   yang baik, anda wajib menguasai bahasa  ini.
Bahasa Mesin, Assembly dan C
Pada dasarnya komputer   adalah makhluk  digital yang hanya mengerti digit 1 dan digit 0   (binary). Komputer hanya  mau menerima data dalam bentuk binary dan juga   hanya bisa mengerti  perintah dalam bentuk binary. Perintah dalam   bentuk binary ini disebut  dengan bahasa mesin.
Secara   umum program bisa dilihat sebagai  urutan langkah/perintah/instruksi   untuk menyelesaikan sesuatu.  Programmer bisa langsung membuat program   dengan menuliskan perintah  dalam bentuk 1 dan 0 (bahasa mesin), atau   menggunakan bahasa tingkat  tinggi yang lebih manusiawi seperti C,   Visual Basic atau Java.
Hanya dua simbol yang dimengerti komputer, yaitu 1 dan 0
Perhatikan   contoh sederhana ini:  programmer ingin menyimpan nilai  register EAX   ke dalam stack. Dalam  bahasa mesin programmer harus menuliskan   01010000. Sedangkan dalam  bahasa assembly programmer cukup menulis PUSH   EAX. Manakah yang lebih  manusiawi? Tentu menggunakan assembly lebih   manusiawi. Sangat sulit bagi  manusia bila harus selalu menggunakan 1   dan 0 setiap memberi perintah.

Semakin tinggi bahasanya, maka semakin    manusiawi cara memberi perintahnya. Contohnya bila programmer ingin    menampilkan suatu teks di layar monitor, dalam bahasa C programmer  cukup   menuliskan printf(“Hello World”), mudah dan singkat. Namun dalam   bahasa  yang lebih rendah seperti assembly, dibutuhkan sekitar 5  langkah  untuk  menyelesaikan tugas yang sama.
Semua   program dalam bahasa apapun  dibuatnya, pada akhirnya ketika akan   dieksekusi akan diterjemahkan dalam  bahasa mesin, karena itulah   satu-satunya bahasa yang dimengerti  prosesor.
Bahasa Assembly dan Processor
Karena   bahasa assembly adalah mnemonic  (singkatan) untuk instruksi dalam   bahasa mesin. Maka perintah-perintah  dalam bahasa assembly terkait erat   dengan prosesornya. Setiap prosesor  memiliki instruction set   masing-masing,sehingga bahasa assembly untuk  prosesor Intel akan   berbeda dengan assembly untuk prosesor lainnya.   Namun karena intel   menguasai pangsa pasar prosesor maka hampir semua  produsen prosesor   membuat instruksi set yang kompatibel dengan intel.
Bahasa assembly adalah mnemonic dari instruksi bahasa mesin (berbentuk binary) yang disebut opcode
Dokumentasi   lengkap mengenai membuat  program dalam prosesor intel, termasuk  daftar  instruction setnya bisa  diperoleh di website resmi intel, di intel developer manuals.    Dalam artikel ini saya hanya menjelaskan beberapa instruksi dasar  yang   paling banyak dipakai, selebihnya bisa dilihat di manual yang ada  di   website intel.
Assembly AT&T dan NASM
Ada   dua sintaks bahasa assembly, yaitu  dalam format AT&T dan NASM.   Sintaks AT&T banyak dipakai dalam  lingkungan GNU seperti GNU   Assembler, dan menjadi format default GNU  Debugger (GDB). Sedangkan   format NASM dipakai oleh netwide assembler dan  banyak dipakai di   lingkungan windows.
Perlu dicatat bahwa perbedaan NASM dan AT&T ini hanya masalah sintaks saja, keduanya menghasilkan bahasa mesin yang sama persis
Beberapa perbedaan antara format AT&T dan NASM adalah:
- Baris komentar diawali dengan “;” semicolon untuk NASM. AT&T mengawali komentar dengan # (hash)
 - Dalam format AT&T, setiap register diawali dengan %. NASM tidak menggunakan %.
 - Dalam format AT&T, setiap nilai literal (konstanta) diawali dengan $. NASM tidak menggunakan $.
 - Pada perintah yang menggunakan operand sumber dan tujuan, format AT&T menuliskan tujuan sebagai operand kedua (contoh: CMD <source>,<dest>). Sedangkan NASM menuliskan tujuan sebagai operand pertama (contoh: CMD <dest>,<source>).
 
Register adalah variabel internal yang    sudah built-in di dalam prosesor yang bisa dipakai oleh programmer   untuk  bermacam-macam keperluan. Karena register posisinya di prosesor,   bukan  di memory, maka menggunakan register sebagai variabel jauh lebih   cepat  dibanding menggunakan variabel yang dismipan di suatu alamat di   memori.
Berikut adalah jenis-jenis register yang ada pada prosesor Intel.
| Kategori | Nama | Penjelasan | 
|---|---|---|
| General Purpose | EAX, EBX, ECX, EDX | Lebar data 32 bit, boleh diapakai untuk keperluan apa saja. E adalah Extended (karena awalnya register general purpose hanya 16 bit). | 
| AX,BX,CX,DX | 16 bit bawah dari register 32 bit di atas. AX adalah bagian 16 bit bawah dari EAX. | |
| AH,AL,BH,BL,CH,CL,DH,DL | Bagian 8 bit dari register 16 bit di atas . AH adalah 8 bit atas dari AX. AL adalah 8 bit bawah dari AX. | |
| Segment Register | CS, SS, DS, ES, FS, GS | Digunakan untuk menunjuk 16 bit awal alamat memori. CS = Code, SS = Stack, DS = Data, ES,FS,GS = Extra segment register | 
| Offset Register | Digunakan untuk menunjuk 16 bit akhir alamat memori. Alamat memori ditunjukkan dengan gabungan segment dan offset. | |
| EBP | Dipakai sebagai offset frame dalam stack. Biasanya menunjuk pada bottom of stack frame di suatu fungsi. ESP menunjukkan puncak stack, EBP menunjuk dasar stack. | |
| ESI | Biasanya dipakai untuk offset string sumber dalam operasi yang melibatkan blok memori. | |
| EDI | Biasanya dipakai untuk offset string tujuan dalam operasi yang melibatkan blok memori. | |
| ESP | Stack pointer, menunjukkan puncak dari stack. | |
| Special | EFLAGS | Tidak bisa dipakai programmer, hanya dipakai prosesor untuk hasil operasi logical dan state. | 
| EIP | Tidak bisa dipakai programmer, hanya dipakai prosesor untuk menunjukkan alamat memori yang berisi instruksi berikutnya yang akan dieksekusi. | 
Perhatikan gambar di   bawah ini untuk  melihat register-register yang ada dalam prosesor   keluarga IA32 (Intel  Architecture 32 bit).
Dalam   gambar di ats terlihat bahwa  register-register Extended (berawalan E)   adalah register 32 bit. Agar  kompatibel program-program sebelumnya   ketika register hanya ada 16 bit,  maka register yang lain adalah bagian   bit bawah dari versi extendednya.  Contohnya adalah register ESI dan   SI. Register SI adalah 16 bit paling  bawah dari ESI. Pada register EAX,   AX adalah 16 bit paling bawah dari  EAX. Register AX pun dipecah lagi   menjadi 8 bit atas AH dan 8 bit bawah  AL. Programmer bebas menggunakan   yang mana saja sesuai kebutuhannya.
The Classic “Hello World”
Cukup   sudah berteori, kini kita mulai  berbasah-basah. Mari kita buat  program  pertama dalam assembly yang  menampilkan teks “Hello World”.  Dalam  artikel ini saya menggunakan  format syntax Intel, bukan  AT&T.  Silakan ketik source berikut dan  simpan dalam nama hello.asm
; section text khusus buat code
section .text
global _start
_start:
; systemcall => write(1,msg,len)
mov edx,len ; panjang string dimasukkan dalam register EDX
mov ecx,msg ; alamat memori yang menyimpan string dimasukkan dalam register ECX
mov ebx,1 ; file descriptor (1=stdout=defaultnya console) disimpan dalam register EBX
mov eax,4 ; Nomor syscall 4 adalah fungsi sys_write()
int 0x80 ; panggil system call dengan interrupt 80 hexa.
; systemcall => exit(0)
xor ebx,ebx ; membuat EBX menjadi 0 sebagai return code ketika exit
mov eax,1 ; nomor syscall 1 adalah fungsi exit()
int 0x80 ; panggil system call dengan interrupt 80 hexa.
section .data ; section data khusus buat data/variable
msg db "Hello, World!",0xa ; String diikuti dengan 0xA yaitu new line \n.
len equ $ - msg ; Panjang string didapat dengan mengurangi address di baris ini dengan alamat string.
Setelah   itu kita akan mengcompile file  ASM itu menjadi object code berformat   ELF dengan NASM (netwide  assembler). Setelah itu akan terbentuk file   hello.o yang harus dilink  dengan linker LD agar menjadi format   executable.
$ nasm -f elf hello.asm
$ ld -s -o hello hello.o
$ ./hello
Hello, World!
Selamat,   anda telah berhasil membuat  program Hello World dalam bahasa  Assembly.  Program di atas sangat  sederhana, kita memanggil system call  write()  untuk menampilkan string  (msg), kemudian kita memanggil  system call  exit() untuk keluar dari  program dan program selesai.  String msg kita  taruh dalam section .data  karena section tersebut  khusus untuk  menyimpan data/variabel. Sedangkan  instruksi assembly  disimpan dalam  section .text karena section text  khusus untuk  menyimpan code.
Hello World OpcodeUntuk melihat keterkaitan antara assembly dan   bahasa  mesin kita bisa melihat opcode dari program assembly yagn kita   buat  dengan program objdump pada gambar berikut ini.

Opcode di sebelah kiri adalah versi bahasa mesin   dari  bahasa assembly di sebelah kanannya. Hal ini menunjukkan eratnya   kaitan  antara assembly dan bahasa mesin. Contohnya adalah instruksi   assembly  INT 0×80 diterjemahkan ke bahasa mesin: 0xCD 0×80 (dalam hexa)   atau  11001101 (binary dari 0xCD) 10000000 (binary dari 0×80).
Perhatikan   bahwa pada source code assembly, “MOV EDX,  len” setelah dicompile   diterjemahkan menjadi “MOV EDX, 0xE”. Hal ini  karena len adalah   konstanta berisi panjang string “Hello, World!” yaitu  sepanjang 14   karakter. Instruksi assembly pada source code “MOV ECX,  msg” setelah   dicompile diterjemahkan menjadi “MOV ECX, 0x80490a4″.  Mengapa msg   diterjemahkan menjadi 0x80490a4? Hal ini karena msg adalah  address dari   string “Hello, World!” sehingga setelah dicompile  diterjemahkan   menjadi alamat 0x80490a4. Terlihat juga pada gambar di  atas pada lokasi   0x80490a4 terdapat string “Hello, World!”.
System CallDalam program hello world di atas kita memanfaatkan    system call untuk menampilkan teks di layar monitor. System call   adalah  gerbang menuju kernel mode bagi program yang membutuhkan servis   yang  hanya bisa dikerjakan oleh kernel.

System call di Linux dipanggil dengan menggunakan    interrupt 80 hexa. Nomor system call dimasukkan dalam register EAX.    Daftar lengkap nomor systemcall di Linux bisa dibaca di file header:    /usr/include/asm/unistd.h. Berikut adalah cuplikan isi dari file    unistd.h
#ifndef _ASM_I386_UNISTD_H_
#define _ASM_I386_UNISTD_H_
/*
* This file contains the system call numbers.
*/
#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_waitpid 7
#define __NR_creat 8
Dalam   contoh hello world kita memanfaatkan system  call nomor 4 (write) dan   nomor 1 (exit). Untuk mengetahui cara pemakaian  dan argumen untuk   system call tersebut, kita bisa gunakan man di Linux.
$ man 2 write
SYNOPSIS
ssize_t write(int fd, const void *buf, size_t count);
$ man 2 exit
void _exit(int status);
Dari   manual system call write meminta 3 argument:  yaitu file descriptor   bertipe integer, alamat memori tempat string  berada, dan terakhir   adalah panjang string bertipe integer. Ketika  argumen tersebut disimpan   dalam register mulai dari EBX, ECX dan EDX.  Argumen pertama di EBX,   argumen kedua di ECX dan ketiga di EDX. Register  EAX dipakai untuk   menyimpan nomor system call. Dari manual system call  exit meminta 1   argument: yaitu kode status bertipe integer yang disimpan  dalam   register EBX.
Dalam contoh hello world di atas   kita menggunakan 3  intruksi assembly yaitu MOV, XOR dan INT. Mari  kita  bahas intstruksi  tersebut.
Instruksi MOV
Kita   menggunakan MOV untuk menyalin data dari sumber  ke tujuan. Sumber dan   tujuan bisa alamat memori, atau register.  Perhatikan contoh berikut:
| NASM/Intel | AT&T | Deskripsi | 
|---|---|---|
| MOV EAX, 0×51 | MOVL $0×51, %EAX | Mengisi register EAX dengan nilai 51 hexa | 
| MOV ESP, EBP | MOVL EBP, ESP | Menyalin isi register EBP ke register ESP | 
Perbedaan antara sintaks NASM dan   AT&T adalah  arah pengkopian. Dalam sintaks NASM, tujuan ada pada   operand pertama,  sedangkan dalam sintaks AT&T tujuan adalah operand   ke-2.
Instruksi XOR
Instruksi   XOR digunakan untuk melakukan operasi  logika Xclusive OR. XOR akan   menghasilkan 0 bila kedua operandnya sama,  dan menghasilkan 1 bila   tidak sama. XOR ini biasanya dipakai untuk  membuat register menjadi 0   dengan melakukan XOR untuk operand yang sama  seperti pada contoh hello   world tersebut.
| NASM/Intel | AT&T | Deskripsi | 
|---|---|---|
| XOR EBX,EAX | XOR %EAX,%EBX | XOR isi EBX dengan EAX, hasilnya disimpan di EBX | 
Instruksi INT
Instruksi   INT digunakan untuk mengirim sinyal  interrupt ke prosesor. Dalam   contoh di atas kita memakai interrupt nomor  80 hexa untuk meminta   layanan dari kernel.
| NASM/Intel | AT&T | Deskripsi | 
|---|---|---|
| INT 0×80 | INT $0×80 | Memanggil interrupt nomor 80 hexa | 
Kali ini kita akan memodifikasi program hello world    di atas agar bisa menampilkan pesan yang sama berkali-kali tergantung    dari argumen yang dimasukkan user.
section .text
global _start
_start:
pop eax ; pop number of argc (diabaikan)
pop eax ; pop argv[0] (diabaikan karena berisi nama program)
pop eax ; pop argv[1] (ini dipakai untuk stringtoint)
call stringtoint ; ECX berisi argumen bertipe integer sebagai counter
_print:
push ecx ; selamatkan counter di stack karena ECX dipakai juga di _print_hello
call _print_hello ; print hello world
pop ecx ; ambil lagi counter dari stack karena akan dipakai untuk looping
loop _print ; kurangi ECX dengan 1, bila belum 0 kembali ke _print
; ini system call exit(0)
mov ebx,0
mov eax,1
int 0x80
_print_hello: ; systemcall write(1,msg,len)
mov edx,len
mov ecx,msg
mov ebx,1
mov eax,4
int 0x80
ret
stringtoint: ; mengubah string di lokasi yang ditunjuk EAX menjadi integer di ECX
; EAX address of string
xor ecx,ecx ; clear ECX
xor ebx,ebx ; clear EBX
mov bl,[eax] ; BL berisi kode ASCII string di lokasi yang ditunjuk EAX
sub bl, 0x30 ; Kode ascii angka adalah 30h-39h, dikurangkan dengan 30h
add ecx,ebx ; ECX ditambah EBX, ECX berisi nilai integer
ret
section .data
msg db "Hello, World!",0xa
len equ $ - msg
Simpan source code di atas dengan nama helloxtimes.asm, lalu compile dan link seperti di bawah ini.
$ nasm -f elf helloxtimes.asm
$ ld -s -o helloxtimes helloxtimes.o
$ ./helloxtimes 1
Hello, World!
$ ./helloxtimes 2
Hello, World!
Hello, World!
$ ./helloxtimes 3
Hello, World!
Hello, World!
Hello, World!
$ ./helloxtimes 4
Hello, World!
Hello, World!
Hello, World!
Hello, World!
Kita belajar   beberapa instruksi baru dalam contoh  ke-2 ini, yaitu looping,   penggunaan argumen dan prosedur, sedangkan  system call yang dipakai   tetap sama, yaitu write() dan exit().
Program   kali ini menerima argumen berupa integer 1-9  yang dipakai sebagai   counter berapa kali pesan akan muncul di monitor.  Argumen ini diambil   dari stack dengan instruksi POP. Pada puncak stack  ada argc, yaitu   jumlah argumen ketika program dijalankan. Di bawahnya  berisi address   dari argv[0] yaitu nama program. Kemudian di bawahnya  lagi baru berisi   address dari argv[1] yaitu parameter/argumen pertama.  Perhatikan pada   baris ke-6 s/d baris ke-8 ada instruksi POP EAX sebanyak  tiga kali.  Ini  dilakukan karena yang diperlukan ada pada posisi ke-3  sehingga  kita  harus membuang 2 elemen di puncak sebelum bisa mengambil  address   argv[1]. Address argumen ke-1 diambil dari POP lalu disimpan  dalam   register EAX. Karena bentuknya masih string, maka harus diubah  dulu   menjadi integer dengan memanggil prosedur stringtoint pada baris  ke-9.
Ketika   program dijalankan dengan satu argumen seperti  “./helloxtimes 7″.  Maka  jumlah argumen (argc) akan berisi 2, yaitu nama  program itu  sendiri,  dan satu argumennya. ARGC akan disimpan pada  puncak stack,  dan elemen  di bawahnya berisi alamat memori dari nama  program, dan  dibawahnya lagi  berisi alamat memori dari argumen pertama.  Perhatikan  gambar di atas  yang menunjukkan proses pengambilan alamat  memori  berisi string argumen  pertama dari stack. Dalam contoh tersebut   argumen adalah string “7″,  yaitu karakter berkode ASCII 37 hexa diikuti   dengan ASCII 0 (karakter  NULL). Alamat memori berisi string argumen   pertama itu diambil dari  stack dan disimpan di register EAX.
Pada   prosedur stringtoint, register EAX berisi  address string yang akan   diubah menjadi integer. Kita hanya mengambil  karakter pertama saja,   pada baris ke-35 dengan instruksi MOV, isi memori  pada address yang   ditunjuk oleh EAX dicopy ke register BL.
“MOV EBX, [EAX]” berbeda dengan “MOV EBX,EAX”. MOV EBX,[EAX] berarti menyalin isi memori pada alamat yang disimpan di EAX ke dalam register EBX. Sedangkan MOV EBX,EAX berarti menyalin isi register EAX ke register EBX
Saya   menggunakan register BL karena kode ASCII  lebarnya hanya 8 bit. Bila   benar berisi angka, maka register BL akan  berisi nilai 30h-39h (kode   ascii untuk “0″-”9″). Setelah itu register BL  dikurangi dengan 30h   untuk mendapatkan nilai dari 0-9. Setelah itu  hasilnya ditambahkan ke   register ECX sehingga kembali dari prosedur ini  dengan nilai integer   hasil konversi di register ECX.
Setelah   mendapatkan nilai argumen bertipe integer di  register ECX, selanjutnya   ECX ini perlu diselamatkan dulu dalam stack  (baris 12) sebab ECX akan   dipakai dalam prosedur _print_hello (baris  13). ECX dipakai sebagai   alamat string msg ketika memanggil system call  write(). Setelah kembali   dari prosedur _print_hello, nilai ECX perlu  dikembalikan seperti   semula dengan POP ECX (baris 14) sebab akan dipakai  sebagai counter   dalam LOOP (baris 15). Ketika menjalankan instruksi  LOOP, register ECX   akan dikurangi 1, kemudian bila ECX > 0 maka  program akan lompat ke   _print. Bila ECX bernilai 0, maka loop berhenti  dan menjalankan  system  call exit(0).
Setelah memahami cara  kerja  program contoh ke-2 itu.  Sekarang mari kita bahas instruksi baru  yang  ada di sana: CALL, RET,  PUSH, POP, LOOP.
Instruksi PUSH dan POPInstruksi PUSH digunakan untuk menyimpan nilai ke    dalam stack. Kebalikannya adalah instruksi POP untuk mengambil nilai    dari stack. Stack dalam Linux membesar ke alamat memori yang lebih    rendah. Puncak stack ada di alamat rendah, sedangkan dasar stack ada di    alamat yang lebih tinggi.
| NASM/Intel | AT&T | Deskripsi | 
|---|---|---|
| PUSH value | PUSHL value | Menyimpan nilai ke dalam stack | 
| POP dest | POPL dest | Mengambil nilai dari stack ke dest | 
Struktur Data Stack
Stack adalah   struktur data yang mirip seperti  tumpukan piring. Data yang diambil   dari stack adalah data yang  dimasukkan terakhir, atau istilahnya adalah   LIFO (last in first out).  Jadi kalau kita ingin mengambil data di   tengah-tengah tumpukan, caranya  adalah dengan mengambil dulu data dari   puncak sampai habis, sehingga  data yang kita inginkan berada di puncak   stack.
Reguster   ESP menunjukkan alamat memori dari puncak  stack. Setiap ada instruksi   PUSH, maka register ESP berkurang (ingat  stack bertumbuh ke alamat  yang  makin mengecil) karena puncak stack  berubah. Begitu pula bila   sebaliknya bila ada instruksi POP, maka  register ESP akan bertambah.
PUSH EAX
PUSH EAX di atas sama dengan dua instruksi di bawah ini:
SUB ESP, 4
MOV DWORD PTR SS:[esp], EAX
PUSH   EAX (4 byte) bisa dilakukan dengan mengurangkan  ESP dengan 4,  kemudian  menyalin isi EAX ke memori di lokasi SS:[ESP],  yaitu di  segment stack  pada offset yang ditunjuk oleh ESP. DWORD PTR   menunjukkan bahwa lebar  data yang akan disalin ke memori dalam  instruksi  MOV itu selebar 4  byte.
POP EAX
POP EAX di atas sama dengan dua instruksi di bawah ini:
MOV EAX, DWORD PTR SS:[esp]
ADD ESP, 4
POP   EAX (4 byte) bisa dilakukan dengan menyalin isi  memori di lokasi   SS:[ESP], yaitu di segment stack pada offset yang  ditunjuk oleh ESP ke   register EAX, lalu menambahkan ESP dengan 4. DWORD  PTR menunjukkan   bahwa lebar data yang akan disalin ke memori dalam  instruksi MOV itu   selebar 4 byte.
Instruksi CALL dan RETInstruksi CALL digunakan untuk memanggil sebuah    prosedur. Sedangkan RET dipakai untuk kembali dari prosedur kembali ke    lokasi setelah instruksi pemanggilan. Ketika instruksi CALL dijalankan,     prosesor menyimpan alamat instruksi sesudah instruksi CALL ke dalam    stack (return address), kemudian prosesor lompat ke alamat subroutine    yang dituju. Ketika instruksi RET dijalankan, maka prosesor mengambil    (POP) return address (alamat yang di-push ketika CALL), kemudian  loncat   ke alamat tersebut.
| NASM/Intel | AT&T | Deskripsi | 
|---|---|---|
| CALL subroutine1 | CALL subroutine1 | Memanggil prosedur subroutine1 | 
| RET | RET | Kembali dari prosedur | 

Instruksi LOOP
LOOP   digunakan untuk melakukan looping sejumlah nilai  yang ada pada   register ECX. Ketika ada instruksi LOOP, prosesor akan  mengurangi nilai   ECX dengan 1, kemudian membandingkan hasilnya. Bila  nilai ECX  sekarang  masih > 0, maka prosesor akan loncat ke alamat  yang  ditunjuk dalam  LOOP. Bila nilai ECX sekarang menjadi 0, prosesor  tidak  akan loncat,  tapi melanjutkan mengerjakan instruksi selanjutnya   setelah LOOP.
| NASM/Intel | AT&T | Deskripsi | 
|---|---|---|
| LOOP address | LOOP address | Looping ke alamat yang ditunjukkan oleh address bila ECX > 0. | 
Instruksi tunggal “LOOP address” ekivalen dengan 2 instruksi assembly berikut:
DEC ECX ; DECREMENT: ECX = ECX - 1, register ECX dikurangi 1
JNZ address ; JUMP IF NOT ZERO: Bila ECX masih belum 0, JUMP ke address

Pada gambar di atas ada dua kondisi yang mungkin    yaitu ECX > 0 atau ECX = 0. Mungkin ada yang bertanya, lho bagaimana    dengan kondisi ECX < 0 ? Ingat komputer hanya mengenal 2 simbol,    yaitu 0 dan 1, jadi pada dasarnya tidak ada “-1″ atau “-0″ dalam    representasi binary. Bilangan negatif direpresntasikan dengan pengkodean    two-complement, silakan baca di signed number representation karena itu diluar topik yang kita bahas sekarang.
Bila   ECX bernilai 0 sebelum mengerjakan instruksi  LOOP, maka yang terjadi   adalah program akan looping sebanyak 0xFFFFFFFF  atau 4.294.967.295   kali. Hal ini terjadi karena 0 – 1 = -1 yang dalam  binary adalah   0xFFFFFFFF dengan sistem two-complement.
				Subscribe to:
				
Posting Komentar (Atom)




0 komentar:
Posting Komentar