Computer Architecture wijanarto
Apa yang anda kerjakan Tentukan CPI dari potongan kode. Tujuan dari tugas ini adalah memahami cara kerja kompiler dan kode yang anda tulis pada komputer anda. Ada 3 tugas pada again ini: 1. Tulis kode C (ada pada halaman selanjutnya) dan jalankan pada kompiler anda. Tentukan seluruh addressing mode yang mungkin tampak pada kompiler anda , lalu tentukan berapa banyak addressing mode ? Dapatkah anda mendokumentasikannya ? Tentukan CPI dari potongan kode. Tulis potongan kode dalam intel assembler .
Sumber-sumber penting Intel Volume 1: Basic Architecture http://developer.intel.com/design/pentium4/manuals/245470.htm Volume 2: Instruction Set Reference http://developer.intel.com/design/pentium4/manuals/245471.htm Volume 3: System Programming Guide http://developer.intel.com/design/pentium4/manuals/245472.htm http://babbage.clarku.edu/~jbreecher/docs/IA32 SDM Vol1 Architecture.pdf http://babbage.clarku.edu/~jbreecher/docs/IA32 SDM Vol2 Instruction Set.pdf http://babbage.clarku.edu/~jbreecher/docs/IA32 SDM Vol3 System Programmers Guide.pdf http://www.penguin.cz/~literakl/intel/intel.html
Sumber-sumber penting Linux, GCC dan GDB GNU Debugger http://www.gnu.org/manual/gdb-4.17/html_mono/gdb.html GCC – Compiler: http://gcc.gnu.org/onlinedocs/gcc-3.0.1/gcc.html Source code : ada pada dokumen ini !
Tugas 1: Tentukan seluruh addressing mode yang mungkin tampak pada kompiler anda , lalu tentukan berapa banyak addressing mode Pada halaman selanjutnya anda akan menemukan kode C untuk melakukan tugas 1 ini, kode ini akan menghasilkan alignment faults. Namun karena prosesor intel merupakan mesin jenis CISC, dia tidak dapat menghasilkan alignment faults, namun kode ini cukup bagus untuk didemonstrasikan dalam C; kode ini juga menunjukan penanganan argumneninput dan bagaimana loop Lakukan pengkodean dalam linux, lalu kompile seperti contoh berikut “gcc -O3 addmode.c” komplie file addmode.c dg optimasi 3, hasilnya a.out “gdb a.out” lakukan disassemble file a.out “disassemble main” disassemle fungsi main Maka ODS akan menghasilkan kode dalam bentuk assembler Anda perlu mengamati output assembler tersebut untukmengidentifikasi seluruh addressing mode. Contoh addressing mode: 0x8048516 <main+118>: movl $0xbc614e,0x8049800(%ebx) Anda juga dapat memodifikasi kode C sehingga kode assembler tsb akan menghasilkan tambahan addressing mode.
File addmode.c #include <stdio.h> #include <stdlib.h> #include <time.h> long global[32]; /* 128 bytes */ int main( int argc, char *argv[ ] ) { long offset; /* jml bytes yg di tambahkan ke lokasi alignment */ long iterations; /* banyaknya waktu utk melakukan opersi ini. */ long *alignment; /* address yg akan kita baca datanya. */ long index; long long_temp = 0; time_t start_time, end_time; if (argc < 3 ) { printf( “Pemakaian batasan <byte offset> <iterations>\n"); exit(0); }
addmode.c offset = atol( argv[1] ); iterations = atol( argv[2] ); printf( "Inputs: Offset: %d Iterations: %d\n", offset, iterations ); alignment = (long *)((long)(&global) + offset); printf( "Global addr: %x Offset Address: %x\n", &global, alignment ); *alignment = 12345678; /* Iterasi untuk nilai LONG */ time ( &start_time ); for ( index = 0; index < iterations; index++ ) long_temp = (*alignment + long_temp) % 47; time( &end_time ); printf( “Waktu utk %d lama iterasi adalah %d detik.\n", iterations, end_time - start_time ); } /* End of main */
Output assembly a.out Huruf cetak merah Komentar/keterangan Dump of assembler code for function main: 0x80484a0 <main>: push %ebp 0x80484a1 <main+1>: mov %esp,%ebp 0x80484a3 <main+3>: sub $0x10,%esp 0x80484a6 <main+6>: push %esi 0x80484a7 <main+7>: push %ebx 0x80484a8 <main+8>: mov 0xc(%ebp),%esi 0x80484ab <main+11>: cmpl $0x2,0x8(%ebp) if (argc < 3 ) 0x80484af <main+15>: jg 0x80484c8 <main+40> 0x80484b1 <main+17>: add $0xfffffff4,%esp 0x80484b4 <main+20>: push $0x80485e0 0x80484b9 <main+25>: call 0x8048398 <printf> 0x80484be <main+30>: add $0xfffffff4,%esp 0x80484c1 <main+33>: push $0x0 0x80484c3 <main+35>: call 0x80483a8 <exit> 0x80484c8 <main+40>: push $0x0 offset = atol( argv[1] ); 0x80484ca <main+42>: push $0xa 0x80484cc <main+44>: push $0x0 0x80484ce <main+46>: pushl 0x4(%esi) 0x80484d1 <main+49>: call 0x8048378 <__strtol_internal> 0x80484d6 <main+54>: mov %eax,%ebx 0x80484d8 <main+56>: add $0x10,%esp 0x80484db <main+59>: push $0x0 iterations = atol( argv[2] ); 0x80484dd <main+61>: push $0xa 0x80484df <main+63>: push $0x0 0x80484e1 <main+65>: pushl 0x8(%esi) 0x80484e4 <main+68>: call 0x8048378 <__strtol_internal> Huruf cetak merah Komentar/keterangan
Output assembly a.out 0x80484e9 <main+73>: mov %eax,%esi 0x80484eb <main+75>: add $0x10,%esp 0x80484ee <main+78>: add $0xfffffffc,%esp 0x80484f1 <main+81>: push %esi 0x80484f2 <main+82>: push %ebx 0x80484f3 <main+83>: push $0x8048620 0x80484f8 <main+88>: call 0x8048398 <printf> printf( "Inputs: Offset: %d .. 0x80484fd <main+93>: lea 0x8049800(%ebx),%eax 0x8048503 <main+99>: add $0xfffffffc,%esp 0x8048506 <main+102>: push %eax 0x8048507 <main+103>: push $0x8049800 0x804850c <main+108>: push $0x8048660 0x8048511 <main+113>: call 0x8048398 <printf> printf( "Global addr: …. 0x8048516 <main+118>: movl $0xbc614e,0x8049800(%ebx) *alignment = 12345678; 0x8048520 <main+128>: add $0x20,%esp 0x8048523 <main+131>: add $0xfffffff4,%esp 0x8048526 <main+134>: lea 0xfffffffc(%ebp),%eax 0x8048529 <main+137>: push %eax 0x804852a <main+138>: call 0x8048368 <time> time ( &start_time );
Output assembly a.out 0x804852f <main+143>: add $0x10,%esp for ( index = 0; index < iterations; index++ ) 0x8048532 <main+146>: lea 0xfffffff8(%ebp),%edx 0x8048535 <main+149>: test %esi,%esi 0x8048537 <main+151>: jle 0x8048543 <main+163> 0x8048539 <main+153>: mov %esi,%eax 0x804853b <main+155>: nop 0x804853c <main+156>: lea 0x0(%esi,1),%esi 0x8048540 <main+160>: dec %eax long_temp = (*alignment + long_temp) % 47; 0x8048541 <main+161>: jne 0x8048540 <main+160> 0x8048543 <main+163>: add $0xfffffff4,%esp 0x8048546 <main+166>: push %edx time ( &end_time ); 0x8048547 <main+167>: call 0x8048368 <time> 0x804854c <main+172>: add $0xfffffffc,%esp printf( "Time f …. 0x804854f <main+175>: mov 0xfffffffc(%ebp),%eax 0x8048552 <main+178>: mov 0xfffffff8(%ebp),%edx 0x8048555 <main+181>: sub %eax,%edx 0x8048557 <main+183>: mov %edx,%eax 0x8048559 <main+185>: push %eax 0x804855a <main+186>: push %esi 0x804855b <main+187>: push $0x80486a0 0x8048560 <main+192>: call 0x8048398 <printf> 0x8048565 <main+197>: lea 0xffffffe8(%ebp),%esp 0x8048568 <main+200>: pop %ebx 0x8048569 <main+201>: pop %esi 0x804856a <main+202>: leave 0x804856b <main+203>: ret 0x804856c <main+204>: lea 0x0(%esi,1),%esi
Menentukan CPI (cycle per instruction) suatu Program. Tugas 2: Menentukan CPI (cycle per instruction) suatu Program. Gunakan kode sebelumnya. Tujuaannya adalah mengambil potongan kode sederhana – misalnya suatu loop didalamnya dan menentukan CPI. Untuk menyelesaikan tugas ini anda perlu : Pikirkan – rumus untuk mendapatkan CPI ? Coba anda cari di internet atau dimana saja Bagaimana cara anda utnuk mendapatkan potongan kode yang di perlukan dan memasukkannya dalam rumus tersebut ? Setiap orang akan memberikan jawaban yang berbeda pada tugas ini. Ada program yang bagus bernama arch_params, hanya dapat di jalankan pada linux, nanti dapat di berikan. Program ini mengasilkan seluru informasi komputer anda, CPU speed (MHz), dsb.
Kode yang perlu anda tambahkan pada addmode untuk menghitung CPI /* tambahankan deklarasi fungsi di bawah ini sebelum fungsi main()*/ void get_current_time( double * ); /* tambahkan definisi variabel di bawah fungsi main*/ double start_seconds; /* Time at start of main loop. */ double end_seconds; /* Time at end of main loop. */ double elapsed_seconds; double cc; double cpu_cc; double cpi; double cpu_cr=0.599; double checkcpur; /* hitung cpu rate utk check kebenaran arch_params*/ /*tambahkan kode di awah ini sebelum loop iterasi*/ get_current_time( &start_seconds ); for ( index = 0; index < iterations; index++ ) long_temp = (*alignment + long_temp) % 47; get_current_time( &end_seconds );
Lanj. /* hitung waktu mengerjakan instruksi for loop */ elapsed_seconds = end_seconds - start_seconds; /* hitung cpu cycle*/ cc= (1/(cpu_cr*pow(10,9))) * pow(10,12) ; printf("CPU cycle = %lf ps cycle time atau \n",cc); printf("CPU cycle = %lf ns cycle time\n",cc*1/1000); /* hitung clock cycle pada loop program */ cpu_cc =elapsed_seconds*(cpu_cr*pow(10,9)); /*check apakah cpu rate menurut arch_params sudah benar */ checkcpur =(cpu_cc/elapsed_seconds)*pow(10,-9); /* hitung CPI */ cpi=cpu_cc/iterations; printf("Check cpu rate = %f GHz\n",checkcpur); printf( "Time for %d iterations of longs is %8.3f seconds.\n", iterations,elapsed_seconds ); printf( "CPU clock cycle = %8.5f cycle\nCPI = %3.3f \n", cpu_cc,cpi);
Lanj. /*definisikan fungsi yang sudah di deklarasikan tadi di bagian paling bawah setelah end of main*/ void get_current_time( double *time_returned ) { struct timeval tp; gettimeofday (&tp, NULL); *time_returned = tp.tv_usec; *time_returned += tp.tv_sec*1000000; *time_returned /= 1E6; } /* End of get_current_time */
Tulis potongan kode Intel Assembler Tugas 3: Tulis potongan kode Intel Assembler Ada 2 cara untuk melakukannya : Tulis kode assembler dan jalankan dengan gcc. GCC mengerti jika extensi file tersebut adalah *.s. Masukan beberapa kode assembler dalam kode C. kompiler Gnu memiliki teknik yang mengijinkan anda untuk menulis kode assembler dalam c. Keuntungan dari ini adalah kita dapat memasukkan input dari kode assembler tanpa khawatir pada pernyataan printf. Tugas anda: Modifikasi kode assembler yang akan diberikan pada halaman selanjutnya. Anda akan menggunakan instruksi intel lainya – bukan hanya instruksi OR. Setelah anda modifikasi anda akan cetak hasilnya dan analisa. Semakin kompleks instruksi yang anda pilih semakin bagus.
Kode untuk tugas 3: asm ("movl %0, %%eax": : "g" (input1)); Pindahkan variabel ‘input1’ ke register eax.” asm ("movl %%eax, %0": "=g" (result) ); Pindahkan isi register eax ke variable ‘result’ Contoh kode yang di kompilasi dan cara menggunakannya wied% gcc -g -o assembler_code assembler_code.c -lm wied% assembler_code 3 9 Input #1: 3: 00000000000000000000000000000011 Input #2: 9: 00000000000000000000000000001001 Result is: 11: 00000000000000000000000000001011 wied%
Kode lengkap untuk tugas 3 Assembler dalam C (inset.c) /********************************************************************* Program ini menunjukan bagaimana melakukan assembler call dari C. *********************************************************************/ #include <stdlib.h> #include <stdio.h> #include <math.h> /*********************************************************************** Definisi makro assembler. Dengan intruksi OR, COBA dg NOT,ato yg lain #define DO_OR(Input_1, Input_2, Result) \ ( { \ asm ("push %eax" ); \ asm ("push %ebx" ); \ asm ("movl %0, %%eax": : "g" (input1)); \ asm ("movl %0, %%ebx": : "g" (input2)); \ asm ("or %ebx, %eax" ); \*instruksi OR*\ asm ("movl %%eax, %0": "=g" (result) ); \ asm ("pop %ebx"); \ asm ("pop %eax"); \ } ) void int_to_binary( unsigned int , char *);
Inset.c /********************************************************************* Program utama. *********************************************************************/ int main( int argc, char *argv[] ) { int input1; /* input argumen 1. */ int input2; /* input argumen 2. */ unsigned int result; /* hasilnya */ char binary_text[40]; if (argc < 3 ) { printf( “Pemakaian: inset <input1> <input2>\n"); exit(0); } input1 = atol( argv[1] ); input2 = atol( argv[2] ); result = 0; int_to_binary( input1, binary_text ); printf( "Input #1: %4d: %s\n", input1, binary_text ); int_to_binary( input2, binary_text ); printf( "Input #2: %4d: %s\n", input2, binary_text ); DO_OR( input1, input2, result ); int_to_binary( result, binary_text ); printf( "Result is: %4d: %s\n", result, binary_text ); } /* End of main */
Inset.c /********************************************************************* Konverter integer ke string dlm binary *********************************************************************/ void int_to_binary( unsigned int input, char *output ) { int index; unsigned int comparison; for ( index = 0; index < 32; index++ ) comparison = pow( (double)2, (double)index ); if ( ( input & comparison ) != 0 ) output[31 - index] = '1'; else output[31 - index] = '0'; } output[32] = '\0'; return; } /* End of int_to_binary */