190 likes | 307 Views
Computer Architecture. wijanarto. Apa yang anda kerjakan. Tujuan dari tugas ini adalah memahami cara kerja kompiler dan kode yang anda tulis pada komputer anda . Ada 3 tugas pada again ini :
E N D
Computer Architecture wijanarto
Apa yang anda kerjakan Tujuandaritugasiniadalahmemahamicarakerjakompilerdankode yang andatulispadakomputeranda. Ada 3 tugaspada again ini: 1. Tuliskode C (adapadahalamanselanjutnya) danjalankanpadakompileranda. Tentukanseluruh addressing mode yang mungkintampakpadakompileranda , lalutentukanberapabanyak addressing mode ? Dapatkahandamendokumentasikannya ? • Tentukan CPI daripotongankode. • Tulispotongankodedalamintel 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 Padahalamanselanjutnyaandaakanmenemukankode C untukmelakukantugas 1 ini, kodeiniakanmenghasilkan alignment faults. Namunkarenaprosesorintelmerupakanmesinjenis CISC, diatidakdapatmenghasilkan alignment faults, namunkodeinicukupbagusuntukdidemonstrasikandalam C; kodeinijugamenunjukanpenangananargumneninputdanbagaimana 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>
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
Tugas 2: Menentukan CPI (cycle per instruction) suatu Program. Gunakankodesebelumnya. Tujuaannyaadalahmengambilpotongankodesederhana – misalnyasuatu loop didalamnyadanmenentukan CPI. Untukmenyelesaikantugasiniandaperlu : • Pikirkan – rumusuntukmendapatkan CPI ? Cobaandacaridi internet ataudimanasaja • Bagaimanacaraandautnukmendapatkanpotongankode yang diperlukandanmemasukkannyadalamrumustersebut ? • Setiaporangakanmemberikanjawaban yang berbedapadatugasini. Ada program yang bagusbernamaarch_params, hanyadapatdijalankanpadalinux, nantidapatdiberikan. Program inimengasilkanseluruinformasikomputeranda, CPU speed (MHz), dsb.
Kode yang perlu anda tambahkan pada addmode untuk menghitung CPI /* tambahankandeklarasifungsidibawahinisebelumfungsi main()*/ void get_current_time( double * ); /* tambahkandefinisivariabeldibawahfungsi 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; /* hitungcpu rate utk check kebenaranarch_params*/ /*tambahkankodediawahinisebelum 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 */
Tugas 3: Tulispotongankode Intel Assembler Ada 2 carauntukmelakukannya : • Tuliskode assembler danjalankandengangcc. GCC mengertijikaextensi file tersebutadalah *.s. • Masukanbeberapakode assembler dalamkode C. kompiler Gnu memilikiteknik yang mengijinkanandauntukmenuliskode assembler dalam c. Keuntungandariiniadalahkitadapatmemasukkan input darikode assembler tanpakhawatirpadapernyataanprintf. Tugasanda: Modifikasikode assembler yang akandiberikanpadahalamanselanjutnya. Andaakanmenggunakaninstruksiintellainya – bukanhanyainstruksi OR. Setelahandamodifikasiandaakancetakhasilnyadananalisa. Semakinkompleksinstruksi yang andapilihsemakinbagus.
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 */