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 lagi.
Artikel ini juga 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 Opcode
Untuk 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 Call
Dalam 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 POP
Instruksi 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 RET
Instruksi 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.
No related posts.




Tidak ada komentar:
Posting Komentar