TEKNIK ELEKTRO ITB
Modul
Praktikum
Arsitektur
Sistem
Komputer
‐
I
EL3110
Modul Ini telah direvisi dan dilengkapi oleh : Andri Haryono (Teknik Elektro 2006) Frillazeus Goltha (Teknik Elektro 2006)
Niko Robbel (Teknik Elektro 2006) Ardianto Satriawan (Teknik Elektro 2007)
Gilang Ilham (Teknik Elektro 2007) Muhammad Johan A (Teknik Elektro 2007)
Umar Abdul Aziz (Teknik Elektro 2007) Tommy Gunawan (Teknik Elektro 2008)
PETUNJUK
PRAKTIKUM
ARSITEKTUR
KOMPUTER
I
KOMPOSISI NILAI
Buku Catatan Laboratorium (BCL) : 20%
PRAKTIKUM : 40 % Ada 6 percobaan dengan bobot 40% dari total penilaian. berikut nilai tiap percobaan (total 100%). NILAI AKTIVITAS PRAKTIKUM : 35 % SOURCE CODE : 40 % NILAI TEST AKHIR : 25% LAPORAN : 40%
TOLERANSI KETERLAMBATAN 15 MENIT
Petunjuk Pembuatan Laporan
1. Laporan hanya terdiri atas identitas praktikan, abstrak, data praktikum, analisis, dan
kesimpulan. Lampiran dan hal lainnya disertakan bila diperlukan. Format terlampir
2. Ketika melampirkan gambar terminal/command prompt, pastikan background
terminal/command promt berwarna putih.
3. Gunakan font courier new pada kode program yang dilampirkan.
#define START_VAL 0 int accum = START_VAL;
int sum(int x, int y)
{ int t = x + y; accum += t; return t; }
4. Hapus folder pekerjaan Anda setiap selesai menggunakan komputer.
5. Disarankan mencoba praktikum terlebih dahulu di rumah.
Bahasa
C
PRAKTIKUM
ARSITEKTUR
KOMPUTER
MODUL
1
KOMPILASI
DAN
DISASSAMBLE
PROGRAM
TUJUAN
Memahami tahap‐tahap kompilasi dari bahasa tingkat tinggi hingga diperoleh file
eksekusi. Memahami cara memeriksa suatu program berbasis bahasa assembly.
ALAT PERCOBAAN
Personal Computer – PC. Compiler GCC pada Operating SystemDASAR TEORI
Sistem KompilasiSuatu program akan mudah dibaca dan dimengerti oleh manusia jika ditulis dalam bahasa tingkat
tinggi, seperti high‐level C program. Tetapi, agar program dapat dijalankan pada sistem komputer,
maka setiap baris pernyataan pada C harus diterjemahkan oleh suatu program lain menjadi urutan
instruksi bahasa mesin tingkat rendah. Instruksi‐instruksi tersebut kemudian dikemas dalam suatu
bentuk yang disebut executable object program dan disimpan dalam file biner.
Langkah‐langkah menerjemahkan baris‐baris kode program pada C menjadi file eksekusi dilakukan
dalam empat langkah meliputi pre‐processor, compiler, assembler, dan linker, yang seluruhnya
disebut sistem kompilasi. Pre-processor (cpp) Compiler (ccl) Assembler (as) Linker (ld) Source program (text) Modified Source program (text) Assembly program (text) Relocatable object program (binary) Executable object program (binary) program.c program i program.s program.o program
Misalkan kita menulis program C dalam dua file p1.c dan p2.c. Kemudian kita mengkompilasi
kode program tersebut dengan mengetikkan command line :
$ gcc –O2 –o prog p1.c p2.c
Perintah gcc merupakan compiler default pada Linux yang menggunakan GNU C Compiler. Secara
sederhana kita juga dapat menggunakan perintah cc. Flag –O2 memerintahkan compiler untuk
melakukan optimasi tingkat‐2. Secara umum, jika tingkat optimasi meningkat maka program akan
kesulitan ketika melakukan debugging kode program. Optimasi tingkat‐2 merupakan kompromi yang
baik antara kinerja optimasi dan kemudahan debugging. Flag –o memerintahkan compiler untuk
memberi nama file eksekusi yang dihasilkan dengan nama prog.
Perintah gcc di atas menerjemahkan kode program menjadi file eksekusi dengan melalui empat
langkah. Pertama C pre‐processor akan memproses semua preprocessor directive, misalnya
#define, atau memasukkan isi file‐file yang tertulis #include directive ke kode program. Kedua, compiler menghasilkan kode assembly untuk setiap file, menjadi p1.s dan p2.s. Selanjutnya, assembler mengkonversi kode assembly menjadi file kode objek biner p1.o dan p2.o. Terakhir, linker menggabungkan kedua file kode objek dengan kode‐kode yang mengimplementasikan fungsi‐
fungsi library Unix standar (mis. printf) dan menghasilkan file eksekusi.
Untuk hanya melakukan preprocessing, kita dapat menggunakan opsi “-E” pada command line :
$ gcc –E p1.c
Untuk melihat kode assembly yang dihasilkan oleh compiler C, kita dapat menggunakan opsi “-S”
pada command line :
$ gcc –O2 –S p1.c
Perintah ini akan menyebabkan compiler hanya menghasilkan file assembly p1.s dan tidak
melakukan langkah berikutnya. Kode assembly yang dihasilkan sesuai dengan format GAS (“Gnu
Assembler”).
Jika pada command line digunakan opsi “-c”, maka GCC akan melakukan ‘compile’ dan ‘assemble’
kode program :
$ gcc –O2 –c p1.c
Perintah ini akan menghasilkan file kode object p1.o, dalam bentuk format biner dan tidak dapat
dilihat secara langsung.
Untuk memeriksa isi dari file kode objek, terdapat suatu program yang bernama disassembler.
Program tersebut dapat melakukan konversi file kode objek menjadi format assembly. Pada sistem
Unix/Linux, program OBJDUMP (singkatan dari “OBJect DUMP”) dapat dipanggil menggunakan flag
“-d” :
$ objdump –d p1.o
Untuk menghasilkan kode yang dapat dieksekusi, kita harus menjalankan linker pada seluruh file
kode objek. Program eksekusi akan dihasilkan dengan menggabungkan seluruh file kode objek pada command line :
$ gcc –O2 –o prog code.o main.c
File program eksekusi prog yang dihasilkan berisi tidak hanya kode yang kita masukkan, tetapi juga
informasi yang digunakan untuk memulai dan mengakhiri program. Kita juga dapat melakukan
dissasamble file prog :
$ objdump –d prog
PERCOBAAN
Percobaan 1 : 1. Buat direktori baru dengan NIM Anda. 2. Buat kode program berikut dengan menggunakan teks editor. #define START_VAL 0int accum = START_VAL;
int sum(int x, int y) {
int t = x + y; accum += t; return t; }
Simpan kode program tersebut dengan nama code.c dalam direktori yang telah Anda buat tadi.
Percobaan 2 :
1. Preprocess code.c dan lihat hasilnya :
$ gcc –E code.c
2. Compile code.c untuk menghasilkan kode assembly :
$ gcc –O2 –S code.c
3. Compile dan assemble code.c untuk menghasilkan file kode objek :
$ gcc –O2 –c code.c
4. Compile dan assemble akan menghasilkan object code. Apa sebetulnya object code ini?
Bagaimana komputer menyimpannya sebagai file?
5. Agar dapat diperoleh program eksekusi, diperlukan adanya fungsi main pada salah satu file kode
objek‐nya. Buatlah file baru dan beri nama main.c.
6. Compile seluruh kode untuk menghasilkan program eksekusi. Beri nama program eksekusi
tersebut prog.
$ gcc –O2 –o prog code.c main.c
7. Bagaimana caranya agar pada main.c variabel accum dan fungsi sum() dapat digunakan?
Beri penjelasan!
8. Buka file code.s dan code.o dengan teks editor. Beri komentar.
Percobaan 3 : 1. Lakukan disassembler pada file kode objek, code.o. $ objdump –d code.o Apa fungsi opsi ‘–d’ pada command line disassembler ? 2. Lakukan disassembler pada file program eksekusi, prog. $ objdump –d prog 3. Bandingkan hasil disassembler file kode object dan file prog. Percobaan 4 : 1. Lakukan kompilasi (seperti percobaan 2) dan disassembler (seperti percobaan 3) dengan tingkat optimasi yang berbeda, yaitu dengan opsi –O1.
2. Bandingkan kode assembler yang dihasilkan antara tingkat optimasi –O1 dengan tingkat
optimasi –O2 seperti yang dilakukan pada percobaan 2 dan 3.
3. Bagaimana dengan -O3 dan -Os?
4. Bagaimana pengaruh tingkat optimasi yang berbeda terhadap size dan speed (terutama antara -O2 dan -O3)?
Percobaan 5 :
1.
Buat kode program berikut dengan menggunakan teks editor. #include "text.h" void main() { test(); }Simpan kode program tersebut dengan nama main_text.c dalam direktori yang telah Anda
buat tadi.
2.
Buat kode program berikut dengan menggunakan teks editor.#include <stdio.h>
void test()
{
printf("Arsitektur Komputer I !\n");
}
Simpan kode program tersebut dengan nama text.c dalam direktori yang telah Anda buat
tadi.
3.
Buat kode program berikut dengan menggunakan teks editor. #ifndef TES_H #define TES_H 100 void test(); #endifSimpan kode program tersebut dengan nama text.h dalam direktori yang telah Anda buat
tadi.
4.
Buat makefile berikut dengan menggunakan teks editor.all: coba
coba: main2.o coba.o
gcc main2.o coba.o -o coba
main_text.o: main_text.c
gcc -c main_text.c
gcc -c text.c
Simpan kode program tersebut dengan nama makefile dalam direktori yang telah Anda buat
tadi.
5.
Jalankan perintah make pada command prompt (NB: Atur terlebih dahulu working direktoriAnda pada direktori yang Anda buat tadi).
6.
Perhatikan! Apa yang terjadi? Beri komentar.7.
Sekarang edit kode program text.c yang telah Anda buat tadi menjadi:#include <stdio.h> #include "text.h" void test() { printf("TES_H = %d\n",TES_H); }
8.
Ulangi langkah 5 dan 6.TUGAS
Buat program fibonacci sederhana, yaitu program yang akan mengeluarkan deret seperti berikut ini 1, 1, 2, 3, 5, 8, 13, … Jumlah deret diinputkan oleh user melalui keyboard. Misal n = 4 akan keluar deret 1, 1, 2, 3. Programterdiri dari dua file C yaitu fibo.c dan inputn.c. inputn.c akan mengatur masalah input n yang
dimasukkan dan fibo.c akan menghitung nilai berdasarkan input n. buatlah makefile yang akan
mengkompilasi program ini.
Lampirkan semua kode yang dibuat pada Lampiran Laporan.
PRAKTIKUM
ARSITEKTUR
KOMPUTER
MODUL
2
REPRESENTASI
DAN
MANIPULASI
LEVEL
BIT
TUJUAN
Memahami representasi informasi pada level bit Melatih melakukan manipulasi informasi pada level bitALAT PERCOBAAN
Personal Computer – PC Software compiler C misalnya MinGW atau GCCDASAR TEORI
Bahasa pemrograman C mendukung operasi Boolean level bit. Simbol yang biasa digunakan untuk
melakukan operasi Boolean pada C adalah : | untuk OR, & untuk AND, ~ untuk NOT, dan ^ untuk
EXCLUSIVE‐OR. Operasi‐operasi ini dapat dilakukan pada berbagai tipe data, seperti char, int, short, long atau unsigned.
Pada operasi logika, C juga mendukung dengan simbol : || untuk operasi logika OR, && untuk
operasi logika AND, dan ! untuk operasi logika NOT. Operasi ini mudah tertukar dengan operasi
Boolean level bit, tetapi sebenarnya kedua operasi ini sangat berbeda. Pada operasi logika, setiap
argumen yang bukan nol merepresentasikan TRUE, sementara argumen nol (0) merepresentasikan
FALSE. Fungsi logika mengembalikan nilai 1 dan 0, yang mengindikasikan TRUE dan FALSE.
Selain operasi Boolean dan operasi logika, terdapat juga operasi shift. C dapat melakukan operasi
shift pada level bit ke kiri dan ke kanan. Pada umumnya, seluruh mesin dapat mendukung dua
bentuk operasi right shift : logical dan arithmetic. Logical right shift mengisi sisi paling kiri dengan bit
0, sementara arithmetic right shift mengisi sisi paling kiri dengan bit tanda yang direpresentasikan
pada MSB.
PERCOBAAN
Pada percobaan ini anda diminta untuk membuat 10 buah fungsi yang berhubungan dengan
representasi dan manipulasi informasi pada level bit. Setiap fungsi harus dilengkapi dengan fungsi
main dan dikompilasi hingga diperoleh file eksekusi‐nya. Penilaian dilakukan berdasarkan kebenaran dari program serta efisiensi penggunaan kode.
Persiapan lingkungan kerja :
Pindah ke direktori kerja anda (nama direktori sama dengan NIM anda). Simpan seluruh program anda pada direktori tersebut.
Fungsi 1 : bitXor(x,y)
Buat fungsi yang memiliki perilaku serupa dengan operasi ^.
Operator yang boleh digunakan hanya & dan ~.
Contoh : bitXor(4,5) = 1
Prototype fungsi : int bitXor(intx, int y)
Fungsi 2 : oddBits(void)
Fungsi evenBits memberikan nilai return satu word, dimana seluruh bit ganjil diset menjadi 1.
Setiap bit pada satu word diberi nomor dari 0 (LSB) hingga 31 (MSB).
Prototype fungsi : int oddBits(void)
Fungsi 3 : getByte(x,n)
Fungsi getByte mengekstrak byte n dari word data x. Urutan byte dalam word diberi nomor dari 0
(LSB) hingga 3 (MSB).
Contoh : getByte(0x12345678,1) = 0x56
Prototype fungsi : int getByte(int x, int n)
Fungsi 4 : bitMask(highbit,lowbit)
Fungsi bitMask menghasilkan suatu mask dimana seluruh bit antara highbit dan lowbit diset
menjadi 1, dan bit sisanya diset menjadi 0.
Asumsi 0 <= lowbit <= 31 dan 0 <= highbit <= 31.
Jika lowbit > highbit, mask seluruhnya 0.
Contoh : bitMask(5,3) = 0x38
Prototype fungsi : int bitMask(int highbit, int lowbit)
Fungsi 5 : reverseBytes(x)
Fungsi reverseBytes membalikkan urutan byte dari input word dengan menukar byte 0 dengan
byte 3, byte 1 dengan byte 2. Urutan byte pada word berurutan dari 0 (LSB) hingga 3 (MSB).
Prototype fungsi : int reverseBytes(int x) Fungsi 6 : tmax(void) Fungsi tmax mengembalikan nilai two’s complement integer terbesar.
Prototype fungsi : int tmax(void)
Fungsi 7 : minBytes(x)
Fungsi minBytes menghitung nilai dari byte data pertama dikurangi byte data kedua. Sistem
bilangan negaif yang digunakan adalah two’s complement. Tidak boleh menggunakan operator
pengurangan (‐), hanya boleh menggunakan penambahan (+) dan invers (~).
Contoh : minBytes(0x15,0x07) = 0x0E
Prototype fungsi : int minBytes(int x, int y)
Fungsi 8 : shiftRegister(x)
Fungsi untuk memasukkan data berdasarkan fungsi shift register pada sistem digital. Asunsi jumlah
bit adalah 32 bit, dan setiap nilai yang dimasukkan adalah 5 bit. Nilai awal register adalah
0x00000000. Contoh :
shiftRegister(0x04)= 0x00000004 (dlm biner 0x...0000000100) shiftRegister(0x13)= 0x00000093 (dlm biner 0x...0010010011)
ket : input sebelumnya berpengaruh pada nilai sekarang.
Prototype fungsi : int shiftRegister (int x)
TUGAS
Buatlah sebuah program enkripsi sederhana yang berfungsi untuk menyamarkan 9 digit
angka. Enkripsi yang akan dibuat adalah dengan melakukan operasi XOR setiap 8 bit dari 32
bit input dengan sebuah angka desimal 8 bit. Contoh : Input angka 123456789 (00000111
01011011 11001101 00010101), angka desimal untuk enkripsi 85. Maka output hasil enkripsi
adalah 1376688192 (01010010 00001110 10011000 01000000). Input 9 digit angka dan
angka desimal untuk mengenkripsi merupakan input keyboard. Buat juga program untuk
dekripsinya!
Buatlah makefile yang akan mengkompilasi program ini.PRAKTIKUM
SISTEM
KOMPUTER
MODUL
3
POINTER
DAN
ARRAY
TUJUAN
Memahami konsep array, pointer dan alokasi memori Melatih penggunaan array dan pointer dalam C dan assemblerALAT PERCOBAAN
Personal Computer – PC Software compiler C misalnya MinGW atau GCCDASAR TEORI
Array adalah kumpulan lokasi penyimpanan data, setiap data menyimpan tipe data yang sama.
Setiap lokasi penyimpanan disebut elemen array
Anda tahu bahwa semua bahasa pemrograman tingkat tinggi menggunakan variabel. Sedangkan
pada bahasa pemrograman tingkat rendah variabel didefinisikan dengan cara yang lebih rumit. Di
sinilah salah satu kelebihan C ditunjukkan, dimana ia dapat menjembatani antara bahasa kelas tinggi
(unggul dengan kemudahan karena konsepnya manusiawi) dengan bahasa tingkat rendah
(powerfull, karena akses maksimal terhadap hardware). Dalam C, programmer memiliki akses
terhadap memory secara langsung dengan menggunakan p o i n t e r . Untuk memahami konsep
pointer, anda perlu mempelajari konsep pengalamatan mempory. Definisi pointer adalah variabel
yang menyimpan alamat memory.
PERCOBAAN
Percobaan 1 :9. Masukkan kode program berikut dengan menggunakan teks editor. Simpan kode program
tersebut dengan nama coba.c
void coba(int* x, int* y, int* z) { int a = *x; int b = *y; int c = *z; int d = a + b; *y = d ;
*z = b ; *x = c ; } 10. Kemudian kompilasi program tersebut agar didapat coba.s, pada file coba.s terdapat angka‐ angka yang menunjukkan penggunaan memory, apa arti angka‐angka tersebut.
11. pada file coba.c ganti keyword int dengan double, kemudian kompilasi file coba.c yang
sudah diubah, lihat kode assembler yang dihasilkan, apakah berbeda dengan yang
sebelumnya ? Mengapa ? seperti sebelumnya pada kode assembler yang dihasilkan akan
muncul angka‐angka, apa arti angka‐angka ini dalam penggunaan memory?
Percobaan 2 :
Pada percobaan ini anda diminta untuk membuat beberapa fungsi yang berkaitan dengan array dan
pointer. Berikan juga penjelasan cara kerja programnya di laporan, terutama yang berhubungan
dengan array dan pointer.
Fungsi 1 :
Buat fungsi yang dapat membaca beberapa karakter dalam array (1 elemen array terdapat 1
karakter) dan menghasilkan output dalam susunan yang terbalik. Contoh: H E L L O menjadi O L L E H Fungsi 2 : Buat fungsi yang dapat melakukan penyimpanan sebuah list (Nama) dalam “two‐dimensional array of char” untuk menampilkan nama. Contoh: Bob Alice Jude Newton Fungsi 3 : Buat fungsi seperti pada Fungsi 2, namun dengan menggunakan “array of pointers” yang menunjuk pada penyimpanan (Nama). Jelaskan perbedaan antara Fungsi 3 dengan Fungsi 2.
Fungsi 4 :
Buat fungsi yang dapat melakukan perkalian pada dua matriks. Keluaran dari fungsi merupakan
matriks hasil perkalian tersebut. Dalam melakukan operasi perkalian matriks gunakan proses loop Contoh : mulMatriks(int A[m][n], int B[n][o]) = C[m][o] = A[m][n] * B[n][o]
Catatan:
Pada fungsi di atas, anda harus dapat membuat agar fungsi mengoutput sebuah matriks. Ada
beberapa cara untuk melakukan ini, misalnya cara paling sederhana adalah membuat matriks
hasilnya sebagai parameter fungsi dan diubah‐ubah nilainya di dalam fungsi (misal C adalah
outputnya):
void addMatriks(int A[m][n], int B[m][n], int C[m][n]);
Tetapi prototype ini memunculkan pertanyaan mengenai kemungkinan implementasi dan cara
pemakaian fungsinya: apakah dari fungsi yang memanggil matriks C hanya merupakan pointer dan
akan dialokasikan nilainya di dalam fungsi, atau matriks C sudah terbentuk sebagai array dan tinggal
diubah nilainya? Biasanya prototype seperti ini lebih cenderung ke cara yang kedua, yaitu array C
sudah ada dan tinggal digunakan. Yang menjadi masalah, dari dalam fungsi tidak ada jaminan bahwa array C sudah teralokasikan dengan benar dan memiliki ukuran yang benar. Apabila ternyata salah,
ada kemungkinan fungsi menulis data ke alamat memori yang sebetulnya bukan milik C (misalnya
karena melebihi batas indeks maksimum array yang dialokasikan untuk C).
Cara lain yang lebih aman adalah membuat fungsi mereturn pointer dari matriks yang dialokasikan secara dinamik di dalam fungsi:
int** addMatriks(int A[m][n], int B[m][n]);
Perhatikan juga bahwa anda harus dapat memberitahukan kepada fungsi berapa nilai m, n, dan o
(ukuran matriks) dari fungsi yang memanggilnya. Cara paling mudah adalah membuat m, n, dan o
sebagai global variable. Namun demikian cara ini biasanya tidak disukai karena penggunaan global
variable membuat alur dan struktur program menjadi kurang jelas, selain membuat fungsi anda
menjadi kurang fleksibel. Cara lain adalah membuat m, n, dan o menjadi parameter fungsi, :
int** mulMatriks(int m, int n, int o, int A[m][n], int B[n][o]);
tetapi ini membuat jumlah parameter fungsi menjadi banyak. Selain itu, dengan menyimpan ukuran
matriks pada variabel terpisah, berarti perlu dibuat dua variabel tambahan, yang secara struktural
dalam program tidak ada hubungannya dengan array matriksnya, untuk menyimpan ukuran matriks.
Salah satu solusi adalah dengan menyimpan matriks dalam suatu struktur data, misalnya yang
sederhana saja: struct Matriks { int jumlahBaris; int jumlahKolom;
int** nilai; // ini akan menjadi dynamic array 2 dimensi };
sehingga prototype fungsi menjadi:
struct Matriks mulMatriks(struct Matriks A, struct Matriks B);
atau jika ingin lebih efisien memori:
struct Matriks* mulMatriks(struct Matriks* pA, struct Matriks* pB);
Anda bebas memilih cara apapun yang disebutkan di atas, atau menggunakan cara lain jika menurut anda lebih baik.
TUGAS
Buatlah sebuah program yang mensimulasikan operasi aritmatika pada level bit 2’s complement
dengan menggunakan array. Array yang digunakan terdiri dari 8 bit saja dan hanya boleh diisi oleh
angka 1 dan 0. Operasi aritmatika yang akan disimulasikan hanya penjumlahan dan pengurangan.
Contoh : penjumlahan antara 7 dan 8. Angka 7 dimasukkan ke dalam array menjadi 00000111 dan
angka 8 menjadi 00001000, maka hasil penjumlahan adalah 00001111 dan kemudian diubah kembali