Bahasa Assembly untuk x86
Sunday, November 18, 2012
Terbagi menjadi 3 bagian utama yaitu :
1.
Komentar
Komentar
diawali dengan tanda titik koma (;).
;
ini adalah komentar
2.
Label
Label
diakhiri dengan tanda titik dua (:).
Contoh:
main: ,loop: ,proses: ,keluar:
3.
Assembler directives
Directives
adalah perintah yang ditujukan kepada assembler ketika sedang menerjemahkan
program kita ke bahasa mesin.
Directive
dimulai dengan tanda titik. .model : memberitahu
assembler berapa memori yang akan dipakai oleh program kita.
Ada
model tiny, model small, model compact, model medium, model large, dan model
huge.
.data : memberitahu assembler bahwa bagian di bawah ini adalah
data program.
.code : memberitahu assembler bahwa bagian di bawah ini adalah
instruksi program.
.stack : memberitahu assembler bahwa program kita memiliki stack.
Program
EXE harus punya stack. Kira-kira yang penting itu dulu.
Semua
directive yang dikenal assembler adalah: .186 .286 .286c .286p .287 .386 .386c
.386p .387 .486 .486p .8086 .8087
.alpha
.break .code .const .continue .cref .data .data? .dosseg .else .elseif .endif
.endw .err .err1 .err2 .errb
.errdef
.errdif .errdifi .erre .erridn .erridni .errnb .errndef .errnz .exit .fardata
.fardata? .if .lall .lfcond .list .listall .listif .listmacro
.listmacroall
.model .no87 .nocref .nolist .nolistif .nolistmacro .radix .repeat .sall .seq
.sfcond .stack
.startup
.tfcond .type .until .untilcxz .while .xall .xcref .xlist.
Definisi data
DB : define bytes. Membentuk data byte demi byte. Data bisa
data numerik maupun teks.
catatan:
untuk membentuk data string, pada akhir string harus diakhiri tanda dolar ($).
sintaks:
{label} DB {data} contoh: teks1 db "Hello world $" DW : define words.
Membentuk
data word demi word (1 word = 2 byte).
sintaks:
{label} DW {data} contoh: kucing dw ?, ?, ? ;mendefinisikan tiga slot 16-bit
yang isinya don’t care
(disimbolkan
dengan tanda tanya)
DD : define double
words. Membentuk data doubleword demi doubleword (4 byte).
sintaks:
{label} DD {data} EQU : equals. Membentuk konstanta. sintaks: {label} EQU {data}
contoh:
sepuluh EQU 10
Ada
assembly yang melibatkan bilangan pecahan (floating point), bilangan bulat
(integer), DF (define far words),
DQ
(define quad words), dan DT (define ten bytes).
Perpindahan data
MOV : move. Memindahkan suatu nilai dari register ke memori,
memori ke register, atau register ke register.
sintaks:
MOV {tujuan}, {sumber}
contoh:
mov AX, 4C00h ;mengisi register AX dengan 4C00(hex).
mov BX, AX ;menyalin isi AX ke BX. mov CL, [BX] ;mengisi register
CL dengan data di memori yang alamatnya ditunjuk BX.
mov CL, [BX] + 2 ;mengisi CL dengan data di memori yang alamatnya
ditunjuk BX lalu geser maju 2 byte.
mov [BX], AX ;menyimpan nilai AX pada tempat di memori yang
ditunjuk BX. mov [BX] – 1, 00101110b
;menyimpan 00101110(bin) pada alamat yang ditunjuk BX lalu geser
mundur 1 byte.
LEA : load effective address. Mengisi suatu register dengan
alamat offset sebuah data.
sintaks:
LEA {register}, {sumber} contoh: lea DX, teks1 XCHG : exchange.
Menukar dua buah register langsung.
sintaks:
XCHG {register 1}, {register 2} Kedua register harus punya ukuran yang sama.
Bila
sama-sama 8 bit (misalnya AH dengan BL) atau sama-sama 16 bit (misalnya CX dan
DX),
maka
pertukaran bisa dilakukan. Sebenarnya masih banyak perintah perpindahan data,
misalnya
IN, OUT, LODS, LODSB, LODSW, MOVS, MOVSB, MOVSW, LDS, LES, LAHF, SAHF, dan XLAT.
Operasi logika
AND : melakukan bitwise and. sintaks: AND {register}, {angka}
AND {register 1}, {register 2} hasil disimpan di register 1.
contoh:
mov AL, 00001011b mov AH, 11001000b and AL, AH ;sekarang AL berisi
00001000(bin),
sedangkan
AH tidak berubah.
OR : melakukan bitwise or. sintaks: OR {register}, {angka} OR
{register 1}, {register 2} hasil disimpan di register 1.
NOT : melakukan bitwise not (one’s complement) sintaks: NOT
{register} hasil disimpan di register itu sendiri.
XOR : melakukan
bitwise eksklusif or. sintaks: XOR {register}, {angka} XOR {register 1},
{register 2} hasil disimpan di register 1. Tips: sebuah register yang
di-XOR-kan dengan dirinya sendiri akan menjadi berisi nol.
SHL : shift left. Menggeser bit ke kiri. Bit paling kanan diisi
nol. sintaks: SHL {register}, {banyaknya}
SHR : shift right. Menggeser bit ke kanan. Bit paling kiri diisi nol.
sintaks: SHR {register}, {banyaknya}
ROL : rotate left. Memutar bit ke kiri. Bit paling kiri jadi
paling kanan kali ini. sintaks: ROL {register},
{banyaknya}
Bila banyaknya rotasi tidak disebutkan, maka nilai yang ada di CL akan
digunakan sebagai banyaknya rotasi.
ROR : rotate right. Memutar bit ke kanan. Bit paling kanan jadi
paling kiri. sintaks: ROR {register},
{banyaknya}
Bila banyaknya rotasi tidak disebutkan, maka nilai yang ada di CL akan
digunakan sebagai banyaknya rotasi.
Ada
lagi : RCL dan RCR.
Operasi matematika
ADD : add. Menjumlahkan dua buah register.
sintaks:
ADD {tujuan}, {sumber} operasi yang terjadi: tujuan = tujuan + sumber.
carry
(bila ada) disimpan di CF.
ADC : add with carry. Menjumlahkan dua register dan carry flag
(CF).
sintaks:
ADC {tujuan}, {sumber} operasi yang terjadi: tujuan = tujuan + sumber + CF.
carry
(bila ada lagi) disimpan lagi di CF.
INC : increment.
Menjumlah isi sebuah register dengan 1.
Bedanya
dengan ADD, perintah INC hanya memakan 1 byte memori sedangkan ADD pakai 3
byte.
sintaks:
INC {register}
SUB : substract.
Mengurangkan dua buah register.
sintaks:
SUB {tujuan}. {sumber} operasi yang terjadi: tujuan = tujuan – sumber.
borrow
(bila terjadi) menyebabkan CF bernilai 1.
SBB : substract with borrow. Mengurangkan dua register dan carry
flag (CF).
sintaks:
SBB {tujuan}, {sumber} operasi yang terjadi: tujuan = tujuan – sumber – CF.
borrow
(bila terjadi lagi) menyebabkan CF dan SF (sign flag) bernilai 1.
DEC : decrement. Mengurang isi sebuah register dengan 1.
Jika
SUB memakai 3 byte memori, DEC hanya memakai 1 byte. sintaks: DEC
{register}
MUL : multiply. Mengalikan register dengan AX atau AH.
sintaks:
MUL {sumber} Bila register sumber adalah 8 bit,
maka
isi register itu dikali dengan isi AL, kemudian disimpan di AX.
Bila
register sumber adalah 16 bit, maka isi register itu dikali dengan isi AX,
kemudian
hasilnya disimpan di DX:AX. Maksudnya, DX berisi high order byte-nya, AX berisi
low order byte-nya.
IMUL : signed multiply. Sama dengan MUL,
hanya
saja IMUL menganggap bit-bit yang ada di register sumber sudah dalam
bentuk two’s complement.
sintaks:
IMUL {sumber}
DIV : divide. Membagi
AX atau DX:AX dengan sebuah register.
sintaks:
DIV {sumber} Bila register sumber adalah 8 bit (misalnya: BL), maka operasi
yang terjadi: -AX dibagi BL,
-hasil
bagi disimpan di AL, -sisa bagi disimpan di AH.
Bila
register sumber adalah 16 bit (misalnya: CX), maka operasi yang terjadi: -DX:AX
dibagi CX, -hasil bagi disimpan di AX, -sisa bagi disimpan di DX.
IDIV : signed divide.
Sama dengan DIV, hanya saja IDIV menganggap bit-bit yang ada di register sumber
sudah dalam bentuk two’s complement.
sintaks:
IDIV {sumber}
NEG : negate. Membuat
isi register menjadi negatif (two’s complement).
Bila
mau one’s complement, gunakan perintah NOT. sintaks: NEG {register} hasil disimpan di
register itu sendiri.
Pengulangan
LOOP : loop. Mengulang sebuah proses. Pertama register CX
dikurangi satu.
Bila
CX sama dengan nol, maka looping berhenti. Bila tidak nol, maka lompat ke label
tujuan.
sintaks:
LOOP {label tujuan} Tips: isi CX dengan nol untuk mendapat jumlah pengulangan
terbanyak.
Karena
nol dikurang satu sama dengan -1, atau dalam notasi two’s
complement menjadi
FFFF(hex) yang sama dengan 65535(dec).
LOOPE : loop while equal. Melakukan pengulangan selama CX ≠ 0 dan
ZF = 1. CX tetap dikurangi 1 sebelum diperiksa.
sintaks:
LOOP {label tujuan}
LOOPZ : loop while zero. Identik dengan LOOPE.
LOOPNE : loop while not equal.
Melakukan
pengulangan selama CX ≠ 0 dan ZF = 0. CX tetap dikurangi 1 sebelum diperiksa.
sintaks:
LOOPNE {label tujuan}
LOOPNZ : loop while not zero. Identik dengan LOOPNE.
REP : repeat. Mengulang perintah sebanyak CX kali. sintaks: REP
{perintah assembly} contoh:
mov CX, 05 rep inc BX ;register BX ditambah 1 sebanyak 5x.
REPE : repeat while equal. Mengulang perintah sebanyak CX kali,
tetapi pengulangan segera dihentikan bila didapati ZF = 1.
sintaks:
REPE {perintah assembly}
REPZ : repeat while zero. Identik dengan REPE.
REPNE : repeat while not equal. Mengulang perintah sebanyak CX
kali, tetapi pengulangan segera dihentikan bila didapati ZF = 0.
sintaks:
REPNE {perintah assembly}
REPNZ : repeat while not zero. Identik dengan REPNE.
Perbandingan
CMP : compare. Membandingkan dua buah operand. Hasilnya
mempengaruhi sejumlah flag register.
sintaks:
CMP {operand 1}, {operand 2}. Operand ini bisa register dengan register ,
register dengan isi memori, atau register dengan angka.
CMP
tidak bisa membandingkan isi memori dengan isi memori. Hasilnya adalah:
Kasus
|
Bila operand 1 < operand 2
|
Bila operand 1 = operand 2
|
Bila operand 1 > operand 2
|
Signed binary
|
OF = 1, SF = 1, ZF = 0
|
OF = 0, SF = 0, ZF = 1
|
OF = 0, SF = 0, ZF = 0
|
Unsigned binary
|
CF = 1, ZF = 0
|
CF = 0, ZF = 1
|
CF = 0, ZF = 0
|
Lompat-lompat
JMP: jump. Lompat tanpa syarat. Lompat begitu saja. sintaks: JMP
{label tujuan}
Lompat bersyarat sintaksnya sama dengan JMP, yaitu perintah jump diikuti
label tujuan.
PERINTAH
|
ARTI
|
SYARAT
|
KASUS
|
KETERANGAN (“OP” = OPERAND)
|
MENGIKUTI CMP?
|
JA
|
jump if above
|
CF = 0 ∧ ZF = 0
|
unsigned
|
lompat bila op 1 > op 2
|
ya
|
JNBE
|
jump if not below or equal
|
||||
JB
|
jump if below
|
CF = 1 ∧ ZF = 0
|
unsigned
|
lompat bila op 1 < op 2
|
ya
|
JNAE
|
jump if not above or equal
|
||||
JAE
|
jump if above or equal
|
CF = 0 ∨ ZF = 1
|
unsigned
|
lompat bila op 1 ≥ op 2
|
ya
|
JNB
|
jump if not below
|
||||
JBE
|
jump if below or equal
|
CF = 1 ∨ ZF = 1
|
unsigned
|
lompat bila op 1 ≤ op 2
|
ya
|
JNA
|
jump if not above
|
||||
JG
|
jump if greater
|
OF = 0 ∧ ZF = 0
|
signed
|
lompat bila op 1 > op 2
|
ya
|
JNLE
|
jump if not less or equal
|
||||
JGE
|
jump if greater or equal
|
OF = 0 ∨ ZF = 1
|
signed
|
lompat bila op 1 ≥ op 2
|
ya
|
JNL
|
jump if not less than
|
||||
JL
|
jump if less than
|
OF = 1 ∧ ZF = 0
|
signed
|
lompat bila op 1 < op 2
|
ya
|
JNGE
|
jump if not greater or equal
|
||||
JLE
|
jump if less or equal
|
OF = 1 ∨ ZF = 1
|
signed
|
lompat bila op 1 ≤ op 2
|
ya
|
JNG
|
jump if not greater
|
||||
JE
|
jump if equal
|
ZF = 1
|
keduanya
|
lompat bila op 1 = op 2
|
ya
|
JZ
|
jump if zero
|
ZF = 1
|
keduanya
|
lompat bila op 1 = op 2
|
ya
|
JNE
|
jump if not equal
|
ZF = 0
|
keduanya
|
lompat bila op 1 ≠ op 2
|
ya
|
JNZ
|
jump if not zero
|
ZF = 0
|
keduanya
|
lompat bila op 1 ≠ op 2
|
ya
|
JC
|
jump if carry
|
CF = 1
|
N/A
|
lompat bila carry flag = 1
|
tidak
|
JNC
|
jump if not carry
|
CF = 0
|
N/A
|
lompat bila carry flag = 0
|
tidak
|
JP
|
jump on parity
|
PF = 1
|
N/A
|
lompat bila parity flag = 1
|
tidak selalu
|
JPE
|
jump on parity even
|
lompat bila bilangan genap
|
|||
JNP
|
jump on not parity
|
PF = 0
|
N/A
|
lompat bila parity flag = 0
|
tidak selalu
|
JPO
|
jump on parity odd
|
lompat bila bilangan ganjil
|
|||
JO
|
jump if overflow
|
OF = 1
|
N/A
|
lompat bila overflow flag = 1
|
tidak
|
JNO
|
jump if not overflow
|
OF = 0
|
N/A
|
lompat bila overflow flag = 0
|
tidak
|
JS
|
jump if sign
|
SF = 1
|
N/A
|
lompat bila bilangan negatif
|
tidak
|
JCXZ
|
jump if CX is zero
|
CX = 0000
|
N/A
|
lompat bila CX berisi nol
|
tidak
|
Operasi stack
PUSH : push. Menambahkan sesuatu ke stack.
Sesuatu
ini harus register berukuran 16 bit (pada 386+ harus 32 bit), tidak boleh
angka, tidak boleh alamat memori.
Maka
Anda tidak bisa mem-push register 8-bit seperti AH, AL, BH, BL, dan
kawan-kawannya.
sintaks:
push {register 16-bit sumber}
contoh:
push DX push AX Setelah operasi push, register SP (stack pointer) otomatis
dikurangi 2 (karena datanya 2 byte).
Makanya,
“top” dari stack seakan-akan “tumbuh turun”.
POP : pop. Mengambil sesuatu dari stack.
Sesuatu
ini akan disimpan di register tujuan dan harus 16-bit. Maka Anda tidak bisa
mem-pop menuju AH, AL, dkk.
sintaks:
POP {register 16-bit tujuan}
contoh:
POP BX Setelah operasi pop, register SP otomatis ditambah 2 (karena 2 byte),
sehingga “top” dari stack “naik” lagi.
Tip:
karena register segmen tidak bisa diisi langsung nilainya, Anda bisa
menggunakan stack sebagai perantaranya.
Contoh
kodenya: mov AX, seg teks1 push AX pop DS
PUSHF : push flags.
Mem-push semua isi register flag ke dalam stack.
Biasa
dipakai untuk membackup data di register flag sebelum operasi matematika. Sintaks:
PUSHF ;(saja).
POPF : pop flags. Lawan dari pushf. Sintaks: POPF ;(saja).
POPA : pop all general-purpose registers.
Adalah
ringkasan dari sejumlah perintah dengan urutan:
pop DI pop SI pop BP pop SP pop BX pop DX pop CX pop AX
Urutan
sudah ditetapkan seperti itu.
sintaks:
POPA ;(saja). Jauh lebih cepat mengetikkan POPA daripada mengetik POP-POP-POP
yang banyak itu.
PUSHA : push all general-purpose registers. Lawan dari POPA,
dimana
PUSHA adalah singkatan dari sejumlah perintah dengan urutan yang sudah
ditetapkan:
push AX push CX push DX push BX push SP push BP push SI push DI
Operasi pada register flag
CLC : clear carry flag. Menjadikan CF = 0. Sintaks: CLC
;(saja).
STC : set carry flag. Menjadikan CF = 1. Sintaks: STC
;(saja).
CMC : complement carry flag. Melakukan operasi NOT pada CF. Yang
tadinya 0 menjadi 1, dan sebaliknya.
CLD : clear direction
flag. Menjadikan DF = 0. Sintaks: CLD ;(saja).
STD : set direction flag. Menjadikan DF = 1.
CLI : clear interrupt flag. Menjadikan IF = 0, sehingga
interrupt ke CPU akan di-disable.
Biasanya
perintah CLI diberikan sebelum menjalankan sebuah proses penting yang riskan
gagal bila diganggu.
STI : set interrupt flag. Menjadikan IF = 1.
Perintah
lainnya
ORG : origin. Mengatur awal dari program (bagian static data).
Analoginya
seperti mengatur dimana letak titik (0, 0) pada koordinat Cartesius.
sintaks:
ORG {alamat awal}
Pada
program COM (program yang berekstensi .com), harus ditulis “ORG 100h” untuk
mengatur alamat mulai dari progam pada 0100(hex),
karena
dari alamat 0000(hex) sampai 00FF(hex) sudah dipesan oleh sistem operasi (DOS).
INT : interrupt.
Menginterupsi prosesor.
Prosesor
akan:
1.
Membackup data registernya saat itu,
2.
Menghentikan apa yang sedang dikerjakannya,
3.
Melompat ke bagian interrupt-handler (entah dimana kita tidak tahu, sudah
ditentukan BIOS dan DOS),
4.
Melakukan interupsi,
5.
Mengembalikan data registernya,
6.
Meneruskan pekerjaan yang tadi ditunda.
sintaks:
INT {nomor interupsi}
IRET : interrupt-handler return.
Kita
bisa membuat interrupt-handler sendiri dengan berbagai cara.
Perintah
IRET adalah perintah yang menandakan bahwa interrupt-handler kita selesai,
dan
prosesor boleh melanjutkan pekerjaan yang tadi tertunda.
CALL : call procedure. Memanggil sebuah prosedur.
sintaks:
CALL {label nama prosedur}
RET : return. Tanda selesai prosedur.
Setiap
prosedur harus memiliki RET di ujungnya.
sintaks:
RET ;(saja)
HLT : halt. Membuat prosesor menjadi tidak aktif.
Prosesor
harus mendapat interupsi dari luar atau di-reset supaya aktif kembali.
Jadi, jangan gunakan perintah HLT untuk mengakhiri program!!
Sintaks:
HLT ;(saja). NOP : no operation.
Perintah
ini memakan 1 byte di memori tetapi tidak menyuruh prosesor melakukan apa-apa
selama 3 clock prosesor.
Berikut
contoh potongan program untuk melakukan delay selama 0,1 detik
pada prosesor Intel 80386 yang berkecepatan 16 MHz.
mov ECX, 533333334d ;ini adalah bilangan desimal idle: nop loop
idle
Buat 5 contoh program dalam bahasa assembly
1. Program assembly pertama
.model small
.code
org 100h
main :
mov AH, 02
mov DL, 65
int 21h
int 20h
end main
Simpan sebagai ‘HurufA.asm’. Kemudian assemble file tadi dengan assembler, misalnya TASM (turbo assembler).
Program kita mengeluarkan output huruf A di layar.
2. Program assembly ke 2
Program ini akan menampilkan sebuah string pada console jika dijalankan.
Berikut ini adalah source codenya:
.386
.MODEL TINY
CSEG SEGMENT PARA PUBLIC USE16 'CODE'
ASSUME CS:CSEG
org 100h
start:
;;Routine utama
pushfd ;save flag
pushad ;save isi semua GPR
;; Menampilkan karakter dilakukan melalui interrupt 10h, service 0Eh
;; dari bios video card, karakter yang akan ditampilkan diberikan
;; melalui register si
lea si,msg
mov ah,0Eh ;gunakan service 0Eh
mov bl,07h ;warna foreground
xor bh,bh ;gunakan page 0, akan muncul bug tanpa ini
MORE_DIS:mov al,cs:0+[si] ;karakter yang akan ditulis ada pada al
cmp al,'$' ;'$' menandakan akhir string
je NO_MORE_DIS
inc si
int 10h ;panggil int 10h (serice dari video bios)
jmp MORE_DIS
NO_MORE_DIS:
popad ;restore semua GPR
popfd ;restore semua flags
retn ;return / akhiri program
;;Definisi Variabel
msg:
DB 10,13
DB 10,13
DB 0,0,0,0,0,0,0,'Your wish is my command',10,13,10,13
DB 0,0,0,0,0,0,0,'Tweaking your chipset...',10,13,'$'
CSEG ENDS
end start
Source code di atas adalah source code dalam masm (Microsoft Assembler).
Program di atas akan menghasilkan output:
Your wish is my command
Tweaking your chipset…
3. Program assembly ke 3
section .data
string db "Vendor ID adalah 'XXXXXXXXXXXX'",0xA
section .text
global _start
_start:
xor eax,eax
cpuid
mov edi,string
mov [edi+25],ebx
mov [edi+29],edx
mov [edi+33],ecx
mov eax,4
mov ebx,1
mov ecx,string
mov edx,41
int 0x80
mov eax,1
xor ebx,ebx
int 0x80
Program ini menghasilkan output berupa Menampilkan ID Vendor prosesor Dengan Instruksi Assembly X86
4. Program assembly ke 4
.MODEL TINY
.CODE
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:CODE,DS:CODE
ORG 0100H
MOV AH,9
INT 21H
RET
DB 'HELLO WORLD$'
CODE ENDS
Program ini akan menampilkan output tulisan "HELLO WORLD"
5. Program assembly ke 5
.486
.MODEL FLAT
.CODE
PUBLIC _myFunc
_myFunc PROC
; Subroutine Prologue
push ebp ; Save the old base pointer value.
mov ebp, esp ; Set the new base pointer value.
sub esp, 4 ; Make room for one 4-byte local variable.
push edi ; Save the values of registers that the function
push esi ; will modify. This function uses EDI and ESI.
; (no need to save EBX, EBP, or ESP)
; Subroutine Body
mov eax, [ebp+8] ; Move value of parameter 1 into EAX
mov esi, [ebp+12] ; Move value of parameter 2 into ESI
mov edi, [ebp+16] ; Move value of parameter 3 into EDI
mov [ebp-4], edi ; Move EDI into the local variable
add [ebp-4], esi ; Add ESI into the local variable
add eax, [ebp-4] ; Add the contents of the local variable
; into EAX (final result)
; Subroutine Epilogue
pop esi ; Recover register values
pop edi
mov esp, ebp ; Deallocate local variables
pop ebp ; Restore the caller's base pointer value
ret
_myFunc ENDP
END
Arsitektur x86
Ada
ALU (aritmethic logic unit), ada register, ada I/O ke system bus, dan ada
interkoneksi internal CPU itu sendiri.
Prosesor
x86 memiliki 5 kelompok register, yaitu:
1. General Purpose Registers Adalah register yang
bisa dipakai untuk berbagai keperluan.
Pada
prosesor 8086 dan 286, register ini besarnya 16 bit. Register yang ada yaitu:
AX : accumulator register. Biasanya dipakai
untuk menyimpan hasil hitungan matematika dan untuk menentukan service
call.
BX : base register. Biasanya dipakai untuk
menunjuk indeks alamat memori.
CX : counter register. Biasanya dipakai untuk
pengulangan (loop).
DX : data register. Biasanya dipakai untuk
menyimpan data keluar/masuk prosesor, serta dipakai di operasi perkalian dan
pembagian.
Register
generik ini masing-masing bisa “dipecah” menjadi dua, satu untuk MSB
(high-order byte) dan satunya lagi untuk LSB (low-order byte).
Register
AX bisa dipecah menjadi AH (AX high) dan AL (AX low), demikian juga ada BH, BL,
CH, CL, DH, DL.
Sebagai
contoh, bila AX sedang berisi 0110 0111 1101 0011(bin), maka AH berisi 0110
0111(bin) dan AL berisi 1101 0011(bin).
Untuk
prosesor 386 ke atas (yang sudah 32 bit), terdapat register EAX (extended AX),
EBX, ECX, dan EDX.
Masing-masing
kapasitasnya 32 bit.
2. Segment Registers adalah register yang tugasnya mencatat blok memori (baca: segmen)
yang sedang digunakan.
Bila
isinya diubah sembarangan, program bisa kacau.
Register
ini kaitannya dengan memori sementara :
CS : code segment. Menunjuk segmen memori
tempat kode program yang sekarang sedang jalan.
DS : data segment. Menunjuk segmen memori
tempat data-data program disimpan (seperti pre-defined string,
buffer string, dan konstanta-konstanta).
SS : stack segment. Menunjuk segmen memori
tempat “top” dari stack saat ini.
“Segmen”nya, bukan “top”nya. Pembahasan tentang stack masih nanti.
ES : extra segment. Adalah register “bonus”
yang belum tentu dipakai, tergantung programnya.
Misalnya untuk menunjuk alamat video memory pada program game yang
fokus pada grafis.
Pada
prosesor 386 ke atas, ada tambahan extra segment lagi yang bernama FS dan GS.
Huruf
“F” dan “G” hanyalah urutan abjad sesudah “E” (ES), tidak ada arti khususnya.
Semua
register segmen, baik di prosesor 16-bit maupun 32-bit, kapasitasnya adalah
16-bit.
3. Pointer Registers Adalah register yang berfungsi sebagai pointer.
Isi
dari register ini adalah alamat memori, makanya dia dikatakan “menunjuk” (to
point)
ke suatu alamat memori tertentu.
Kapasitas
register pointer adalah 16 bit. Karena hanya 16 bit, maka tentu saja tidak
semua alamat memori bisa ditunjuknya.
Besar
memori yang mampu ditangani hanya 216 byte = 64 KB (saja),
sangat kecil.
Padahal
prosesor 16 bit bisa menangani memori sampai 1 MB.
Maka
dari itu, register pointer ini bekerja berpasangan dengan register segmen
menghasilkan alamat memori lengkap,
dan
mampu menangani sampai 1 MB.
SP : stack pointer. Menunjuk ke “top” dari
stack-nya langsung.
Operasi push dan pop akan mengubah isi dari SP. Penjelasan tentang
stack masih nanti.
BP : base pointer. Menunjuk ke sebuah alamat
di bagian data program.
Bekerjasama dengan DS. Biasa dipakai untuk menunjuk elemen array.
IP : instruction pointer. Menunjuk ke alamat
memori tempat instruksi berikutnya, di bagian kode program.
Anggap saja IP adalah program counter (PC). Register ini
diubah otomatis sejalan dengan jalannya program.
Pada prosesor 386 ke atas, terdapat register ESP, EBP, dan EIP
yang kapasitasnya 32 bit
sehingga mampu menangani memori sampai 232 byte =
4 GB.
4. Index Registers Register ini digunakan oleh operasi string dan block
transfer di memori.
SI : source index.
DI : destination index.
Kapasitasnya
16 bit. Pada prosesor 386 ke atas, terdapat ESI dan EDI yang kapasitasnya 32
bit.
5. Flag Registers Namanya juga “bendera”, register ini berfungsi menandakan
suatu keadaan “ya” (mengibarkan bendera)
atau
“tidak” (tidak mengibarkan bendera). Tentu saja tidak ada bendera di dalam CPU
Anda,
yang
ada hanyalah bit 1 atau 0. Register bendera ini masing-masing besarnya 1 bit
saja.
OF : overflow register. Bila terjadi overflow
pada operasi matematika, maka OF bernilai 1. Bila tidak, isi 0.
SF : sign flag. Jika suatu operasi
menghasilkan angka negatif, SF berisi 1.
ZF : zero flag. Jika suatu operasi
menghasilkan angka nol, ZF berisi 1.
CF : carry flag. Berisi
bit carry pada operasi penjumlahan atau bit borrow pada
operasi pengurangan.
DF : direction flag. Menunjukkan arah
pembacaan byte (maju atau mundur) pada operasi string.
PF : parity flag. Bila angka yang dihitung
genap atau ganjil (tergantung sistemnya mau genap apa ganjil), PF berisi 1.
AF : auxiliary flag. Berisi 1 setelah
penjumlahan dua bilangan BCD. Fungsinya seperti carry flag (CF) setelah bit
ke-4 (bukan ke-8)
TF : trap flag. Menunjukkan mode debugging on
atau off. Ini urusan internal CPU.
IF : interrupt flag. Bila IF bernilai 0, maka
interupsi ke prosesor akan diabaikan.
Register
yang hanya terdapat di 80286 ke atas:
NT : nested task.
IOPL : I/O protection level. (2 bit)
PE : protection enable.
MP : monitor co-processor.
EM : emulate co-processor.
TS : task switched.
ET : extention type.
RF : resume flag.
VF : virtual 8086 mode.
Jadi
itulah register yang ada di prosesor Pentium/AMD (x86).
Lebih
sedikit dibanding MIPS karena di MIPS ada 32 register dimana 16 diantaranya
adalah general purpose,
masih
ditambah lagi 12 register general-purpose untuk floating point. Semuanya
32 bit.
Di
x86, register general purpose cuma 4, 16 bit saja.
Makanya
ketika mendesain program, manfaatkan sumberdaya prosesor yang terbatas ini
sebaik-baiknya.
Manajemen
memori
- Bagian “reserved” sudah diatur
oleh sistem operasi dan tidak bisa kita utak-atik lagi.
Untuk program COM (program DOS yang berekstensi .com), bagian reserved ini sudah pasti ukurannya dan letaknya,
yaitu dari alamat memori 0000(hex) sampai 00FF(hex). - Bagian static data berisi data
terdefinisi yang tidak berubah,
seperti konstanta, string terdefinisi, dan buffer. - Bagian program adalah instruksi-instruksi
program yang nanti kita tulis dalam bahasa assembly.
Tentu yang dijalankan oleh prosesor bukanlah bahasa assembly-nya, tapi sudah dalam bentuk bahasa mesin. - Bagian dynamic data, tempat
dimana variabel temporer berada.
Perintah “malloc” di bahasa C memesan tempat di bagian ini.
Dynamic data bisa membesar dan mengecil, tergantung banyaknya data yang diciptakan dan dihapus. - Terakhir adalah stack, memori
yang pasti disediakan di setiap program.
Dasar dari stack terletak di alamat paling tinggi, dan tumbuh turun ke bawah.
Nah, “top” dari stack bisa saja tabrakan dengan dynamic data; jika demikian akan muncul error “stack overflow.”
Memori
di komputer kita yang hitungannya sudah gigabyte, dibagi-bagi menjadi beberapa
blok (dikenal sebagai segmen).
Satu
segmen berukuran 64 KB.
Apa
bedanya program COM dan EXE? Program COM maksimal memakai memori hanya satu segmen,
yaitu
64 KB (makanya kecil sekali). Zaman DOS dulu (dimana memori kecil dan sangat
mahal), banyak sekali program COM.
Sebaliknya,
program EXE bisa memakai lebih dari satu segmen.
Bisa
saja static data-nya banyak sekali, sampai disimpan bersegmen-segmen.
Stacknya
juga barangkali banyak sekali, memakai puluhan segmen.
Coba
jalankan Microsoft Word (winword.exe), lalu buka task manager.
Lihat
memori yang dipakainya (di bagian private use working set).
Waktu
pertama kali dijalankan, di komputer saya tertampil 14280 KB.
Bagi
dengan 64, maka Microsoft Word ini memakai 224 segmen di RAM.
Bermain dengan alamat memori
Dikenal
dua jenis alamat memori. Yang pertama adalah alamat absolut, yaitu alamat yang
secara fisik diakses oleh prosesor.
Yang
kedua adalah alamat relatif, yaitu alamat yang didasarkan pada pembagian segmen
dan pergeseran (offset).
Misalkan
kita kembali ke zaman dulu, dimana prosesor masih 16-bit dan memori komputer
masih 1 MB.
Satu
megabyte berarti 1024 KB, sama dengan 1.048.576 byte. Setiap byte ini punya
alamat absolut masing-masing, yaitu dari 00000(hex) sampai FFFFF(hex).
Komputer
membagi memori 1 MB tadi seperti ini:
Segmen
0000(hex) dimulai dari alamat absolut 00000(hex) sampai 0FFFF(hex) (alamat 0 –
65535).
Segmen
0001(hex) dimulai dari alamat absolut 00010(hex) sampai 1000F(hex) (16 –
65551).
Dan
seterusnya sampai segmen FFFF(hex).
Cara
mengubah alamat relatif ke alamat absolut:
1.
Kalikan angka segmen dengan 16(dec) (= 10(hex))
2.
Kemudian jumlahkan dengan offset-nya.
Notasi
untuk alamat relatif adalah [segmen]:[offset] dalam heksadesimal. Misal
0000:0001 dan FF87:550A.
Pembagian
seperti tadi mengakibatkan adanya tumpang tindih (overlap) antarsegmen.
Ilustrasinya:
+0
|
+1
|
+2
|
+3
|
+4
|
+5
|
+6
|
+7
|
+8
|
+9
|
+A
|
+B
|
+C
|
+D
|
+E
|
+F
|
|
0001
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
0002
|
x
|
x
|
x
|
x
|
x
|
x
|
X
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
0003
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
X
|
x
|
x
|
x
|
x
|
x
|
0004
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
0005
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
x
|
Dalam
tabel ini, baris adalah segmen, kolom adalah offset.
Tanda x adalah byte yang
saat itu ada di memori.
Lihat
byte yang saya tandai dengan merah (tanda x warna merah) itu.
Kita
boleh bilang bahwa dia terletak di segmen 0002 digeser 6 byte, bukan? Maka
alamat relatifnya adalah 0002:0006.
Tapi
kita juga boleh bilang kalau dia terletak di segmen 0001 digeser 22 byte (=
16(hex)) bukan?
Kalau
begitu alamatnya menjadi 0001:0016. Baik 0002:0006
maupun 0001:0016 menunjuk ke alamat absolut yang sama, yaitu 00026(hex).
Demikian
juga byte yang saya tandai dengan warna hijau. Dia bisa diakses dengan:
Alamat absolut = 0003A(hex)
Alamat relatif #1 = 0003:000A
Alamat relatif #2 = 0002:001A
Alamat relatif #3 = 0001:002A
Pada
alamat relatif #1, “0003″ disimpan pada register segmen (entah itu SS, DS, CS,
atau ES).
Sedangkan
“000A” disimpan pada register pointer (entah itu SP, IP, atau BP).
Ilustrasi
di atas sebenarnya kurang tepat, karena saya menggambarkan satu segmen sebesar
16 byte saja.
Kenyataannya,
satu segmen adalah 64 KB.
dari : berbagai sumber
http://end4su.wordpress.com/2009/06/18/assembler/