Veri Yapıları ve Algoritmalar Giriş Öğr. Gör. M. Ozan AKI r1.0
Genel Tanımlar ve Kavramlar
Donanım Mimarileri DEP (Data Execution Preventation) Win7: Bilgisayarım -> Özellikler -> Gelişmiş Ayarlar -> Sistem özellikleri -> Advanced - > Performance -> Ayarlar -> Data Execution Prevention
CISC / RISC Komut Seti CISC (Complex Instruction Set Computer) Örn: 8086/8088 AAA, AAD, AAM, AAS, ADC, ADD, AND, CALL, CBW, CLC, CLD, CLI, CMC, CMP, CMPSB, CMPSW, CWD, DAA, DAS, DEC, DIV, ESC, HLT, IDIV, IMUL, IN, INC, INT, INTO, IRET, JA, JAE, JB, JBE, JC, JCXZ, JE, JG, JGE, JL, JLE, JNA, JNAE, JNB, JNBE, JNC, JNE, JNG, JNGE, JNL, JNLE, JNO, JNP, JNS, JNZ, JO, JP, JPE, JPO, JS, JZ, JMP, LAHF, LDS, LEA, LES, LOCK, LODSB, LODSW, LOOP, MOV, MOVSB, MOVSW, MUL, NEG, NOP, NOT, OR, OUT, POP, POPF, PUSH, PUSHF, RCL, RCR, REP, REPE, REPNE, REPNZ, REPZ, RET, RETN, RETF, ROL, ROR, SAHF, SAL, SAR, SBB, SCASB, SCASW, SHL, SHR, STC, STD, STI, STOSB, STOSW, SUB, TEST, WAIT, XCHG, XLAT, XOR RISC (Reduced Instruction Set Computer) Örn: PIC16F84A ADDWF, ANDWF, CLRF, CLRW, COMF, DECF, DECFSZ, INCF, INCFSZ, IORWF, MOVF, MOVWF, NOP, RLF, RRF, SUBWF, SWAPF, XORWF, BCF, BSF, BTFSC, BTFSS, ADDLW, ANDLW, CALL, CLRWDT, GOTO, IORLW, MOVLW, RETFIE, RETLW, RETURN, SLEEP, SUBLW, XORLW
CISC CMP A,B JB X MOV AX,[A] JMP Z X: MOV AX,[B] Z: MOV [C],AX CISC vs RISC A ve B Bellek adreslerindeki iki sayıyı karşılaştıralım ve büyük olan sayıyı C adresine yazalım RISC MOVF B,W SUBWF A,W BTFSS STATUS,C GOTO X MOVF A,W GOTO Z X: MOVF B,W Z: MOVWF C
Mikroişemci Reset Vector İlk Enerji verildiğinde ya da Resetlendiğinde Çalıştırılacak komutların başlangıç adresidir. Genelde 0x0000 adresidir. Fetch & Execution Komutların bellekten sırasıyla alınır işlenmesidir. Bu işlem içinde ayrıca işemci zamanı harcanır. (Pipeline?) Flags (PSW Program Status Word) Çalışma durumu ve komutların çalışma sonuçları ile ilgili bilgilerin bit olarak tutulduğu kaydedicidir. Instruction Pointer (IP) / Program Counter (PC) Komutları sırasıyla çalışmasını sağlayan sayaçtır. Bu sayaç dallanma komutları ile değiştirilerek komut işleyişinin sırası değiştirilir. (Kaç bit olmalı?)
Mikroişemci 8086 Program Status Word (PSW) Flag Register
Fiziksel Ortamına Göre Bellek Çeşitleri
Erişim Durumuna Göre Bellek Çeşitleri Analoji: Depo -> Toptancı -> Market, Bakkal -> Dolap, Buzdolabı -> Tabak Bardak
Belleğin Adreslenmesi Register Doğrudan kaydedici adı ile kullanılırlar, bellek adresleri söz konusu değildir. (Instruction Word içerisinde kodlanmıştır) Bellek Bellek adresi ile kullanılırlar. Her adres bir bellek hücresine işaret eder. Her hücre, veriyolu bit sayısı kadar veri saklar
İşletim Sistemleri (Operating Systems) POST süreci başarıyla tamamlandıktan sonra BIOS, Disk, CD- ROM, Flash bellek gibi depolama aygıtlarında yükleyici arar (Boot Loader; XP:NTLDR, WIN7:BOOTMGR, Linux:LILO vs.) ve bulduğunda görevi yükleyiciye devreder. Yükleyici ise işletim sistemini başlatır. İşletim Sisteminin Görevleri CPU Yönetimi Görev Zaman Paylaşımı Giriş-Çıkış İşlemleri Ana Bellek Yönetimi Dosya Sistemi (Disk) Yönetimi Kullanıcı Yönetimi Güvenlik ve Koruma
Yazılım (Software) Makine Dili (Machine Language) Komut setlerini oluşturan ikili sayılar doğrudan mikroişlemciye girilebilir. Birleştirici Dil (Assembly) İnsan tarafından okunabilir ve anlaşılabilir OPCODE lar makine diline çevrilir. Kaynak Kod (Source Code) Yüksek seviyeli dillerin kaynak kodlarını makine diline çevirerek object file olarak kaydeder. Compiler (Derleyici) Yüksek seviyeli dillerin kaynak kodlarını makine diline çevirerek object file olarak kaydeder. Cross Compiler (Çapraz Derleyici) Yüksek seviyeli dillerin kaynak kodlarını üzerinde çalıştığı makineden farklı bir işlemcinin makine diline çevirerek object file olarak kaydeder. Linker (Bağlayıcı) Daha önce derlenmiş olan object dosyaları birleştirerek çalıştırılabilir (COM, EXE, BIN, HEX) dosyayı elde eder ve kaydeder.
Programlama Dilleri Programlama Dillerinde Dört yaklaşım vardır; Prosedürel Yönelimli (Fortran, Pascal,..) Nesne Yönelimli (C++, C#, Java,..) Mantık Yönelimli (Prolog,..) Görev Yönelimli (Verilog, SQL, Mathematica,..) Programlama Dilleri, Veri yapıları ve Algoritmalardan oluşur. Veri Yapısı (Data Structure), bilgilerin bellekte bulunma şeklini belirler. Tüm programlama dillerinde temel veri yapıları tanımlıdır. (char, int, double, float,...) Veri Modeli (Data Model), Verilerin birbirleriyle ilişkisel ve sırasal durumunu ortaya koyar. (Dizi, Liste, Ağaç, Graf,...) Algoritma, Belirli bir işi ya da görevi yerine getirebilmek için uygulanması gereken adımların açıkça ortaya konmasıdır.
Ham Veriden Bilgiye Dönüşüm Bellekte tutulan tüm bilgiler sadece bit dizileri şeklindedir. Bu bit dizileri, sistematik bir şekilde yorumlanarak anlamlı bilgilere dönüştürülür. Örneğin 0 1 0 0 0 0 0 1 bit dizisi için; Tamsayı -> 65 Hexadecimal -> 41 BCD -> 41 ASCII -> A Benzer şekilde, bilgisayar ortamında bulunan tüm veriler (döküman, resim, ses, video, v.s.) tanımlı veri yapılarından türetilmiş ikili kodlar şeklindedir. Ya da, bu ikili kodlara uygun veri yapıları türetilir.
Veri Yapıları Hemen hemen tüm sayısal sistemlerde bilgi temel bilgi boyutu BYTE tır. BYTE ı aşan veriler için WORD ifadesi kullanılır. Bir Byte, 8 bitten oluşur. Gerektiğinde Byte üst katları kullanılır. Byte Kilo Byte Mega Byte Giga Byte Peta Byte Üst katlar gerçekte 1024 kat artar. Bazı işletim sistemleri kolaylık bakımından 1000 kat olarak alır. Bu durumda gerçek boyut ile görünen boyut arasında fark oluşur. Örn: 2GB Bir bellekte; 1000 kat hesabı ile; 2*1000*1000*1000 = 2,000,000,000 Byte, 1024 kat hesabı ile; 2*1024*1024*1024 = 2,147,483,648 Byte Bululunur. Gerçek kapasite 147MB daha büyüktür.
Temel Veri Yapıları Hemen her derleyicide temel veri yapıları küçük farklılıklarla birlikte aynıdır. Bazı derleyiciler, kendine özgü veri yapıları içerebilir. Eğer algoritmaya uygun veri yapıları bulunmuyor ise bunu kullanıcı kendisi tanımlamalıdır. Karakter İşaretli / İşaretsiz Tamsayılar Gerçel Sayılar
Karakterlerin Kodlanması Tüm derleyicilerde bulunan temel veri yapısıdır. char 1 Byte (8 Bit) uzunluğundadır. ASCII tablosundaki karakterlerin tanımlanması amacıyla kullanılır. Ancak bunun yanında 8 bit işaretsiz tamsayı olarak ta işlemlere katılabilir. 8 Bit (255 karakter), Standart ASCII tablosunun tümünü adresler. (ALT + Keypad ASCII Code)
UNICODE Karakter Kodlaması Ancak günümüzde farklı alfabelerin ve kullanılan özel karakterlerin tanımlarını kapsamak üzere geliştirilen bu kodlama sistemi 16 bitlik bir tabloyo tanımlar. Toplam 65535 karakter içeren bu tabloda her bir karakter 16 bit olarak kaydedilir. Böylece, evrensel bir kod tablosu ile, uluslar arası yazılımların kolayca yazılması ve uyumluluk sorunlarının ortadan kaldırılması sağlanmıştır. Uygulama:Aynı bilgiyi içeren UNICODE bir metin dosyası ile ASCII bir metin dosyasının boyutlarını karşılaştırınız.
İşaretsiz Tam Sayıların Kodlaması Tamsayılar, İşaretli ya da İşaretsiz olarak tanımlanırlar. İşaretsiz tamsayılar, bellekte doğal karşılığı ile saklanırlar. Bu sayılar, derleyinin varsayılan bit sayısı (8, 16, 32, 64) ile sınırlıdırlar. Örneğin; 39 Sayısı, 8 bit genişliğindeki bellekte 0 0 1 0 0 1 1 1 olarak saklanır. Eğer bellek hüzcresinin bit genişliği daha fazla ise, üst bitler 0 (sıfır) ile doldurulur.
İşaretli Tam Sayıların Kodlaması İşaretli Tamsayılarda durum biraz farklılaşır; Aynı bit sayısına sahip bir alanda kodlanacak işaretli sayı ile işaretsiz sayının maksimum ve minimum değerleri farklı olur. Neden? Çünkü işaretli sayının değer bitlerinden biri işaret biti olarak kullanılmak zorundadır. Bu nedenle, İşaretsiz bir tamsayı, 0 < n < 2 n -1 aralığında iken, İşaretli bir tamsayı, -2 n-1 < n < 2 n-1-1 aralığında olur.
İşaretli Tam Sayıların Kodlaması İşaretli Tamsayılar iki yöntemle kodlanabilir; 1) Sayının en solundaki bit işaret biti kabul edilir ve negatif sayılar için bu bir 1, pozitif sayılar için 0 yapılır. 2) İşaret biti için özel bir alan ayrılmaz, negatif sayılar 2 ye tümleyen şeklinde saklanır.
Tam Sayıların Kapladıkları Alanlar short int unsigned short int unsigned int int long int signed char unsigned char -32,768 -> +32,767 (16 bit) 0 -> +65,535 (16 bit) 0 -> +4,294,967,295 (32 bit) -2,147,483,648 -> +2,147,483,647 (32 bit) -2,147,483,648 -> +2,147,483,647 (32 bit) -128 -> +127 (8 bit) 0 -> +255 (8 bit) Uygulama: C ile tanımlanan bir tamsayı değişkeninin maksimum ve minimum değerlerini gösteren c programını yazınız.
Gerçek (Kesirli) Sayılar İki tip gösterim şekli vardır; Sabit Noktalı (Fixed Point) Kayan Noktalı (Floating Point) Bilgisayar uygulamalarında büyük çoğunlukla Kayar Noktalı sayılar kullanılmaktadır. Ancak kısıtlı bellek ve işlemci gücüne sahip gömülü sistemlerde sabit noktalı sayılar tercih edilir.
Gerçek (Kesirli) Sayılar Kayan Noktalı (Floating Point) Sayı Formatı (IEEE 754) Bu formatta; 1 bit : İşaret biti (sign) 8 bit : Üs (exponent) 2 ye Tümleyen şeklinde bulunur. 23 bit : Çarpan (fraction) Sayı = ±Ç x T ±Ü (T:Taban=2) http://www.h-schmidt.net/floatconverter/
Gerçek Sayıların Çözümlenmesi Örn; 2.5 sayısını IEEE 754 formatında göstriniz. 2.5 = (-1) i (1 + k) 2 üs-bias Burada; i : sayının işareti (0:Pozitif ya da 1:Negatif) (1+k) : Çarpan (1 <= Ç < 2, k < 0) bias : sabit (32 bit formda: 127, 64 bit formda:1023) i=0 2.5 / 2 n = (1+k) n=1 için, 2.5 / 2 = (1 + k), k = 0.25 Böylece, 2.5 = IEEE 754 formatında 1.25 2 1 olarak gösterilir.
Gerçek Sayıların Çözümlenmesi Örn; 3.14 Pi sayısını IEEE 754 formatında göstriniz. 3.14 = (-1) i (1 + k) 2 üs-bias Burada; i : sayının işareti (0:Pozitif ya da 1:Negatif) (1+k) : Çarpan (1 <= Ç < 2, k < 0) bias : sabit (32 bit formda: 127, 64 bit formda:1023) i=0 3.14 / 2 n = (1+k) n=1 için, 3.14 / 2 = (1 + k), k = 0.57 Böylece, 3.14 = IEEE 754 formatında 1.57 2 1 olarak gösterilir.
Gerçek (Kesirli) Sayıların Kapladığı Alan
Bellek ile Veri Yapısı Bit Sayısı Eğer veri yapısını bit sayısı, belleğin tek adres hücresinde saklanamayacak kadar büyük ise, bu veri yapısı, ardaşık bellek alanlarını kullanır. (Little Endian, Big Endian)
C Dili Anahtar Sözcükleri Anahtar sözcükler, değişken, fonksiyon adı olarak kullanılamazlar. auto, break, case, char, const, continue, default, do, double, else, enum, extern, float, for, goto, if, int, long, register, return, short, signed, sizeof, static, struct, switch, typedef, union, unsigned, void, volatile, while
Fonsiyonlar Fonksiyonlara gönderiler sabit değer ya da değişkenlere parametre adı verilir. Fonksiyonlardan elde edilen sonuç ise dönüş değeri olarak adlandırılır. Bir fonksiyon, Hiçbir parametre almayıp, Hiçbir değer döndürmüyor olabilir. Sadece parametre alıp, Değer döndürmüyor olabilir Hiçbir parametre almayıp, Değer döndürüyor olabilir. Fonksiyonlar, birden fazla parametre alabilir ancak, sadece bir değer döndürebilirler. (Birden fazla değer gerekirse ne olacak?)
Fonsiyonlar Fonksiyonlar, dönüş adreslerini Yığın (Stack) Bellekte saklar. Yığın bellek, en son girenin ilk çıktığı (LIFO) bir bellek türüdür. PUSH, POP Ancak Fonksiyonlar Parametre alıyor ya da Değer Döndürüyor ise, Bu değerlerde yine Yığın Bellek üzerine kaydedilerek fonksiyon çağırılır. İç içe çağırılan fonksiyonlarda Yığın bellek kümülatif olarak dolar. Bu nedenle, özellikle Recursive (Yinelemeli kendi kendini çağıran) fonksiyonlar Yığın bellek taşmalarına (Stack Overflow) neden olabilir.
Karakter Dizileri (String) Karakter dizileri, bellekte ardaşık olarak dizilmiş anlamlı karakterler bütünüdür. Programlamada anlamlı olan karakter dizisi uzunlu açıkça belirtilmiş olmalıdır. Bunun için, farklı diller farklı yaklaşımlar getirmişlerdir; Pascal / Delphi dillerinde karakter dizilerinin uzunluğu ilk karakerde saklanır. isim[] = [19, T, r, a, k, y, a,,u, n, i, v, e, r, s, i, t, e, s, i] C / C++ dillerinde ise karakter dizisi NULL, \0 ile bitmek zorundadır. isim[] = [T, r, a, k, y, a,,u, n, i, v, e, r, s, i, t, e, s, i, \0]
Diziler Belleğin ardaşık adreslerinde aynı veri tipindeki değişkenlerin saklanması yoluyla diziler elde edilir. Diziler, birçok veri modeli için uygun bir veri yapısı sunar. Böylelikle liste, yığın, graf, ağaç gibi yapılar diziler üzerinde kolayca uygulanabilir. C dilinde diziler, doğrudan değişken bildirimi sırasında tanımlanır; int boy[20]; float kilo[25]; char *ad[40]; char harf[29]; float yillik_oran[12][31]; int xyz[10][20][30];
Diziler Öntanımlı veri tipleri dışında, struct yapıları kullanılarak özel dizilerde kolayca oluşturulabilir; struct tarih { unsigned char gun; unsigned char ay; short int yil; } struct tarih dogum_gunleri[2000];
Structure & Union Structure yapısı içerisinde C dilinin ön tanımlı veri tipleri kullanıldığı gibi, bit sayıları özelleştirilerek özel yapılar oluşturulabilir. Bu, özellikle çeşitli dosya formatlarının okunup yazılmasında oldukça kullanışlıdır. Bunun yanında Structure ve Union birlikte kullanılarak değişkenlere bitsel düzeyde erişim de sağlanabilir; Örn; IEEE 754 Sayı Formatının Bitlerini struct ve union ile ayırabiliriz union { } ortak; float f; struct { } bit; unsigned carpan:23; unsigned us:8; unsigned isaret:1;
Structure & Union Örneğin 8 bitlik bir sayıyı bitlerine ayırabilir, isteiğimiz bir biti okuyabilir ya da değiştirebiliriz. union { } sayi; unsigned char butun; struct { unsigned b0:1; unsigned b1:1; unsigned b2:1; unsigned b3:1; unsigned b4:1; unsigned b5:1; unsigned b6:1; unsigned b7:1; } bit;
Structure & Union Daha güncel uygulamalar için, örneğin personel kaydı tutan bir programda her bir personel kaydı struct olarak tanımlanabilir. struct tarih { unsigned char gun; unsigned char ay; unsigned short yil; }; struct personel { char tc_no[11]; char ad[20]; char soyad[20]; tarih dogum_tar; tarih ise_baslama; int maas_carpan; } ; Sizde okul numaranızı struct ile çözümleyerek birinci öğretim, ikinci öğretim, kayıt yılı, okul kodu, bölüm ve sıra numarası bilgilerini çıkarınız.
Operatörler ile Bit Maskeleme Bir abc integer değişkenin 3. biti 1 ise; if(abc & 0x0008) {... } Bir abc integer değişkenin 6. biti 0 ise; if((abc & 0x0040)==0) {... } Bir abc integer sayının 2. bitini 1 yapalım; abc = 0x0004; // (abc = abc 0x0004) Bir abc integer değişkenin 4. bitini 0 yapalım; abc &= ~0x0010; // abc = abc & (~0x0010)
Operatörler ile Bit Maskeleme Bir abc integer değişkenin 3,4,5. bitlerini başka bir değişkene alın; baska = (abc & 0x0038) >> 3; Bir abc integer değişkenin 6,7,8. bitlerin yerine 5 sayısını yazalım; abc = (abc & ~(0x01C0)) (5<<5); 16 bit integer bir değişkenin üst 8 biti ile alt 8 bitini yer değiştirin; yeni = (abc & 0x00ff)<<8 (abc & 0xff00)>>8; integer bir sayının 1., 4., 7. bitleri aynı anda 1 olduğunda doğru (true) döndüren ifadeyi yazınız if(abc&0x0092) {... }
Operatörler ile Bit Maskeleme Bir sayının bitlerini en sağdaki bit en solda, en soldaki bit en sağda olacak şekilde tersine çeviren programı yazınız unsigned char i, sayi, yeni=0; sayi=??; int bitsay = 8*sizeof(sayi); for(i=0; i<bitsay; i++) { if(sayi&(1<<i)) yeni =1<<(bitsay-i-1); } printf("yeni= %u\n", yeni);