Organisasi Sistem Komputer
Bagian 8
Bagian 8
Struktur Data
Pembahasan
Tipe data dasar
pe data dasa
Array : alokasi, pengaksesan
Loop array
Loop array
Nested array
Array multi-level
Array multi level
Tipe Data Dasar
Integer
disimpan dan beroperasi pada register umum
signed atau unsigned tergantung dari instruksi yang dipakai
Intel GAS Byte C
byte b 1 [unsigned] char
word w 2 [unsigned] short
double word l 4 [unsigned] int
Floating Point
disimpan dan beroperasi pada register khusus floating point
Intel GAS Byte C
Single s 4 float
Double l 8 double
Alokasi Array
Prinsip dasar :
T A[L];
Array dengan tipe data T dan panjang L
Area yang dialokasikan secara berurutan : L * sizeof(T) byte
char nama[12]; char nama[12]; x x + 12 int val[5]; x x + 4 x + 8 x + 12 x + 16 x + 20 double nilai[4]; x + 32 x + 24 x x + 8 x + 16 char *p[3]; char p[3]; x x + 4 x + 8
Mengakses Array
Prinsip dasar :
T A[L];
Array dengan tipe data T dan panjang L
Identifier A dapat digunakan sebagai pointer ke elemen array 0
val[0] val[1] val[2] val[3] val[4]
1 5 2 1 3
int val[5];
x x + 4 x + 8 x + 12 x + 16 x + 20
Referensi
Tipe
Nilai
val[4] int 3 val int * x 4 val+1 int * x + 4 &val[2] int * x + 8 val[5] int ?? *(val+1)( a ) intt 55 val + i int * x + 4 i
Contoh Array
typedef int kode pos[5];yp _pkode_pos itb = { 4, 0, 1, 3, 2 }; kode_pos mit = { 0, 2, 1, 3, 9 }; kode pos cmu = { 1 5 2 1 3 }; kode_pos cmu = { 1, 5, 2, 1, 3 }; kode_pos itb; 4 0 1 3 2 16 20 24 28 32 36 kode_pos mit; 0 2 1 3 9 36 40 44 48 52 56 36 40 44 48 52 56 kode_pos cmu; 1 5 2 1 3 56 60 64 68 72 76 Catatan :
Deklarasi “kode_pos itb” ekivalen dengan “int itb[5]”
Setiap array dialokasikan berurutan dengan panjang setiap blok 20 byte.
h l d k l l d d h
Contoh Mengakses Array
int get_digit(kode pos z int dig)
Perhitungan :
Register
%edx
berisi alamat awal
(kode_pos z, int dig) {return z[dig]; }
Register %edx
berisi alamat awal
array
Register %eax
berisi indeks array
Di it
dii i k
b
d
d
Digit yang diinginkan berada pada
4*%eax + %edx
Menggunakan referensi memori
(% d
%
4)
Memory Reference Code
(%edx,%eax,4)
# %edx = z # %eax = dig
Contoh Melakukan Referensi
kode_pos itb; 4 0 1 3 2 16 20 24 28 32 36 16 20 24 28 32 36 kode_pos mit; 0 2 1 3 9 36 40 44 48 52 56 kode_pos cmu; 1 5 2 1 3 56 60 64 68 72 76Referensi
Alamat
Nilai
Jaminan Valid?
mit[3] 36 + 4* 3 = 48 3 mit[5] 36 + 4* 5 = 56 1
Ya
Ya
Tidak
=cmu[0]?
Tidak
=cmu[0]?
mit[5] 36 + 4 5 = 56 1 mit[-1] 36 + 4*-1 = 32 2 itb[15] 16 + 4*15 = 76 ?? Kode tidak melakukan pengecekan kebenaran
Tidak =cmu[0]?
Tidak =cmu[0]?
Tidak =itb[4]?
Tidak =itb[4]?
Tidak
Tidak
Kode tidak melakukan pengecekan kebenaran
Loop Array
int kode2int(kode pos z)int kode2int(kode_pos z) { int i; int zi = 0; 0Kode asal
for (i = 0; i < 5; i++) { zi = 10 * zi + z[i]; } return zi;; } int kode2int(kode_pos z) {Versi hasil transformasi
dihasilkan oleh GCC
{int zi = 0;
int *zend = z + 4; do {
dihasilkan oleh GCC
Mengeliminasi loop variabel i
Konversi kode array menjadi
kode pointer
zi = 10 * zi + *z;z++;
} while(z <= zend); return zi;
kode pointer
Diekspresikan dalam bentuk
do-while
Tidak perlu tes ketika
;}
Tidak perlu tes ketika
Loop Array
int zd2int(zip_dig z) { int zd2int(zip_dig z) { int zd2int(zip_dig z) { int zd2int(zip_dig z) { int kode2int(kode_pos z) {Register :
%ecx
z
%eax zi % b d { int zi = 0; int *zend = z + 4; do { i 10 * i * { int zi = 0; int *zend = z + 4; do { i 10 * i * { int zi = 0; int *zend = z + 4; do { i 10 * i * { int zi = 0; int *zend = z + 4; do { i 10 * i * { int zi = 0; int *zend = z + 4; do { i 10 * i * %ebx zendPerhitungan :
10*zi + *z diimplementasikan j di * 2*( i 4* i) zi = 10 * zi + *z; z++; } while(z <= zend); return zi; zi = 10 * zi + *z; z++; } while(z <= zend); return zi; zi = 10 * zi + *z; z++; } while(z <= zend); return zi; zi = 10 * zi + *z; z++; } while(z <= zend); return zi; zi = 10 * zi + *z; z++; } while(z <= zend); return zi; # %ecx = z l % % # i 0 menjadi *z + 2*(zi+4*zi) z++ bertambah 4 ; } # %ecx = z l % % # i 0 ; } # %ecx = z l % % # i 0 ; } # %ecx = z l % % # i 0 ; } # %ecx = z l % % # i 0 ; } xorl %eax,%eax # zi = 0leal 16(%ecx),%ebx # zend = z+4 .L59:
leal (%eax,%eax,4),%edx # 5*zi
xorl %eax,%eax # zi = 0
leal 16(%ecx),%ebx # zend = z+4 .L59:
leal (%eax,%eax,4),%edx # 5*zi
xorl %eax,%eax # zi = 0
leal 16(%ecx),%ebx # zend = z+4 .L59:
leal (%eax,%eax,4),%edx # 5*zi
xorl %eax,%eax # zi = 0
leal 16(%ecx),%ebx # zend = z+4 .L59:
leal (%eax,%eax,4),%edx # 5*zi
xorl %eax,%eax # zi = 0
leal 16(%ecx),%ebx # zend = z+4 .L59:
leal (%eax,%eax,4),%edx # 5*zi
movl (%ecx),%eax # *z
addl $4,%ecx # z++
leal (%eax,%edx,2),%eax # zi = *z + 2*(5*zi)
cmpl %ebx %ecx # z : zend
movl (%ecx),%eax # *z
addl $4,%ecx # z++
leal (%eax,%edx,2),%eax # zi = *z + 2*(5*zi)
cmpl %ebx %ecx # z : zend
movl (%ecx),%eax # *z
addl $4,%ecx # z++
leal (%eax,%edx,2),%eax # zi = *z + 2*(5*zi)
cmpl %ebx %ecx # z : zend
movl (%ecx),%eax # *z
addl $4,%ecx # z++
leal (%eax,%edx,2),%eax # zi = *z + 2*(5*zi)
cmpl %ebx %ecx # z : zend
movl (%ecx),%eax # *z
addl $4,%ecx # z++
leal (%eax,%edx,2),%eax # zi = *z + 2*(5*zi)
cmpl %ebx %ecx # z : zend
cmpl %ebx,%ecx # z : zend
jle .L59 # if <= goto loop
cmpl %ebx,%ecx # z : zend
jle .L59 # if <= goto loop
cmpl %ebx,%ecx # z : zend
jle .L59 # if <= goto loop
cmpl %ebx,%ecx # z : zend
jle .L59 # if <= goto loop
cmpl %ebx,%ecx # z : zend
Nested Array
typedef int kode_pos[5]; kode pos pgh[4] = kode_pos pgh[4] = {{1, 5, 2, 0, 6}, {1, 5, 2, 1, 3 }, {1, 5, 2, 1, 7 }, {1, 5, 2, 2, 1 }}; kode_pos 1 5 2 0 6 1 5 2 1 3 1 5 2 1 7 1 5 2 2 1 _ pgh[4]; 76 96 116 136 156 1 5 2 0 6 1 5 2 1 3 1 5 2 1 7 1 5 2 2 1Deklarasi “kode_pos pgh[4]” ekivalen dengan “int pgh[4][5]”
Variabel pgh
merupakan array dengan 4 elemen
dialokasikan seca a be
tan
dialokasikan secara berurutan
Masing-masing elemen merupakan array dengan 5 int
dialokasikan secara berurutan
Alokasi Nested Array
Deklarasi
T
A[
R
][
C
];
A[0][0] • • • A[0][C-1]
Array dari tipe data
T
R
baris,
C
kolom
Elemen type
T
memerlukan
K
• • • • • •
Elemen type
T
memerlukan
K
byte
Ukuran Array
R
*
C
*
K
b t
A[R-1][0] • • • A[R-1][C-1]
R
*
C
*
K
bytes
Pengaturan
Row-Major Ordering
int A[R][C];int A[R][C];A [0] [0] A [0] [C-1] • • • A [1] [0] A [1] [C-1] • • • A [R-1] [0] A [R-1] [C-1] • • • • • • [ ] [ ] [ ] [ ] [ ] [ ] 4*R*C Bytes
Mengakses Baris Nested Array
Vektor baris
A[i]
adalah array dengan C
y
g
elemen
Masing-masing elemen bertipe T
Dimulai dari alamat A +
i
*
C
*
K
A[i] A[R 1] A[0] int A[R][C]; • • • A [i] A [i] • • • A[i] A [R-1] A [R-1] • • • A[R-1] • • • A [0] A [0] • • • A[0] [0] [C-1] [0] [C-1] A [0] [C-1] A+i*C*4 A+(R-1)*C*4
Kode Mengakses Baris
int *get_pgh_zip(int index) {
Vektor baris
{
return pgh[index]; }
pgh[index]
adalah array dengan 5 int
Dimulai dari alamat pgh+20*index
Kode
Kode
Menghitung dan mengembalikan alamat
Perhitungan : pgh + 4*(index+4*index)
# %eax = index
leal (%eax,%eax,4),%eax # 5 * index( , , ), #
Mengakses Elemen Array
Elemen array
A[i][j]
adalah elemen dengan tipe
T
A [i]
A[i][j]
adalah elemen dengan tipe T
Alamat A +
(
i
*
C
+
j
) *
K
[j] int A[R][C]; A[i] A[R-1] A[0] [ ][ ]; • • • • • • A [i] [j] • • • A [R-1] [0] A [R-1] [C-1] • • • • • • A [0] [0] A [0] [C-1] • • • A A+i*C*4 A+(R-1)*C*4 A+(i*C+j)*4Kode Akses Elemen Array
Elemen array
pgh[index][dig]
adalah int
int get_pgh_digit(i t i d i t di )
Alamat :
pgh + 20*index + 4*dig
Kode
(int index, int dig) { return pgh[index][dig]; }
Kode
Perhitungan alamat
pgh + 4*dig +
4*(index+4*index)
4*(index+4*index)
movl
melakukan referensi memori
# %ecx = dig# %eax = index
leal 0(,%ecx,4),%edx # 4*dig leal (%eax,%eax,4),%eax # 5*index
movl pgh(%edx %eax 4) %eax # *(pgh + 4*dig + 20*index) movl pgh(%edx,%eax,4),%eax # (pgh + 4 dig + 20 index)
Contoh Referensi Unik
kode_pospgh[4]; 1 5 2 0 6 1 5 2 1 3 1 5 2 1 7 1 5 2 2 1
Referensi
Alamat
Nilai
Jaminan ?
pg [ ];
76 96 116 136 156
Referensi
Alamat
Nilai
Jaminan ?
pgh[3][3]
76+20*3+4*3 = 148
2
pgh[2][5]
76+20*2+4*5 = 136
1
Ya
Ya
Ya
Ya
pgh[2][-1] 76+20*2+4*-1 = 112
3
pgh[4][-1] 76+20*4+4*-1 = 152
1
pgh[0][19] 76+20*0+4*19 = 152
1
Ya
Ya
Ya
Ya
Ya
Ya
pgh[0][-1] 76+20*0+4*-1 = 72
??
Kode tidak melakukan pengecekan kebenaran
Elemen array dijamin berurutan
Ya
Ya
Tidak
Tidak
Contoh Array Multi Level
Variabel univ adalah
array dengan 3 elemen typedef int kode_pos[5];kode pos itb = { 4 0 1 3 2 }; array dengan 3 elemen
Masing-masing elemen merupakan pointer 4 byte kode_pos itb = { 4, 0, 1, 3, 2 }; kode_pos mit = { 0, 2, 1, 3, 9 }; kode_pos cmu = { 1, 5, 2, 1, 3 };
int *univ[3] = {mit itb cmu}; y
Masing-masing pointer
menunjuk ke array int
int *univ[3] = {mit, itb, cmu};
itb 36 160 univ itb 4 0 1 3 2 16 20 24 28 32 36 mit 0 2 1 3 9 16 56 164 168 0 2 1 3 9 36 40 44 48 52 56 cmu 1 5 2 1 3 56 60 64 68 72 76
Akses Elemen Array Multi Level
int get_univ_digit(int index, int dig)
Perhitungan
Akses elemen
{ return univ[index][dig]; }Mem[Mem[univ+4*index]+4*dig]
Melakukan dua kali pembacaan memori
Pertama, ambil pointer ke baris array
Pertama, ambil pointer ke baris array
Kemudian, mengakses elemen pada array
# %ecx = index
# % di
# %eax = dig
leal 0(,%ecx,4),%edx # 4*index
movl univ(%edx),%edx # Mem[univ+4*index] movl (%edx,%eax,4),%eax # Mem[...+4*dig], , , g
Mengakses Elemen Array
Referensi C
Nested Array
Perhitungan alama berbeda
Multi-Level Array
int get_pgh_digit(int index, int dig) {
int get_univ_digit
(int index, int dig) { { return pgh[index][dig]; } { return univ[index][dig]; }
Elemen pada
Mem[pgh+20*index+4*dig]
Elemen pada
Mem[Mem[univ+4*index]+4*d
ig]
36 160 16 56 164 168 univ cmu 1 5 2 1 3 16 20 24 28 32 36 mit 0 2 1 3 9 36 40 44 48 52 56 ucb 36 160 16 56 164 168 univ 36 160 16 56 164 168 univ cmu 1 5 2 1 3 16 20 24 28 32 36 1 5 2 1 3 1 5 2 1 3 16 20 24 28 32 36 mit 0 2 1 3 9 36 40 44 48 52 56 0 2 1 3 9 0 2 1 3 9 36 40 44 48 52 56 ucb 76 96 116 136 156 1 5 2 0 6 1 5 2 1 3 1 5 2 1 7 1 5 2 2 1 76 96 116 136 156 1 5 2 0 6 1 5 2 1 3 1 5 2 1 7 1 5 2 2 1 1 5 2 0 6 1 5 2 0 6 1 5 2 1 31 5 2 1 3 1 5 2 1 71 5 2 1 7 1 5 2 2 11 5 2 2 1 56 168 9 4 7 2 0 56 60 64 68 72 76 56 168 56 168 9 4 7 2 0 56 60 64 68 72 76 9 4 7 2 0 9 4 7 2 0 56 60 64 68 72 76 76 96 116 136 156 76 96 116 136 156Contoh Referensi Unik
univ itb 4 0 1 3 2 16 20 24 28 32 36 36 160 16 56 164 168 16 20 24 28 32 36 mit 0 2 1 3 9 36 40 44 48 52 56 cmuReferensi Alamat Nilai Jaminan ?
56 168 1 5 2 1 3 56 60 64 68 72 76 e e e s a at a Ja a univ[2][3] 56+4*3 = 68 1 univ[1][5] 16+4*5 = 36 0 univ[2][-1] 56+4*-1 = 52 9 Ya Ya Tidak Tidak Tidak Tidak [ ][ ] univ[3][-1] ?? ?? univ[1][12] 16+4*12 = 64 2
Kode tidak melakukan pengecekan kebenaran
Tidak Tidak Tidak Tidak Tidak Tidak
Kode tidak melakukan pengecekan kebenaran
Menggunakan Nested Array
Kelebihan
l
#define N 16
t d f i t fi t i [N][N]
Compiler C menangani array
secara double
Menghasilkan kode sangat
f
typedef int fix_matrix[N][N];
/* Compute element i,k of /
efisien
Menghindari perhitungan
indeks ganda
K t b t
fixed matrix product */ int fix_prod_ele
(fix_matrix a, fix_matrix b, int i, int k)
Keterbatasan
Hanya bekerja jika ukuran
array tetap
, ) { int j; int result = 0; f (j 0 j < N j++) for (j = 0; j < N; j++) result += a[i][j]*b[j][k]; return result; } A (i,*) B (*,k) B i A B Kolom BarisNested Array Dinamik
Kelebihan
Dapat membuat matriks
int * new_var_matrix(int n) {
Dapat membuat matriks
dengan urutan tertentu
Pemrograman
P hit
i d k h
{ return (int *) calloc(sizeof(int), n*n); }
Perhitungan indeks harus
secara eksplisit
Kinerja
int var_ele
(int *a, int i, int j, int n)
Biaya mengakses satu
elemen cukup besar
Harus melakukan perkalian
int j, int n) { return a[i*n+j]; } movl 12(%ebp),%eax # i movl 8(%ebp),%edx # a imull 20(%ebp),%eax # n*i
16 #
Perkalian Array Dinamik
Tanpa optimisasi
P k li
/* Compute element i,k of
variable matrix product */ int var prod ele
Perkalian
2 untuk subscript
1 data data
int var_prod_ele (int *a, int *b,
int i, int k, int n) {
Penjumlahan
4 untuk indeks array
1 untuk indeks loop
int j;
int result = 0;
for (j = 0; j < n; j++) result +=
1 untuk indeks loop
1 untuk data
result + a[i*n+j] * b[j*n+k]; return result; } (*,k) A (i,*) B Baris KolomOptimisasi Perkalian Array Dinamik
Optimisasi
Terjadi jika level optimisasi
di-{ int j; int result = 0; for (j = 0; j < n; j++)
j
j
p
set -O2
Pergerakan kode
Ekspresi
i*n
dapat dihitung
for (j = 0; j < n; j++) result +=
a[i*n+j] * b[j*n+k]; return result;