Program sayacı

1952'de tanıtılan IBM 701'in ön paneli; ortadaki ışıklar çeşitli yazmaçların içeriğini gösterir, program sayacı sol alttadır.

Program sayacı (İngilizce: program counter, PC), bir işlemcinin bir sonraki getireceği buyruğun bellek adresini tutan özel bir yazmaçtır. Buyruk işaretçisi (İngilizce: instruction pointer) olarak da anılır. Program sayacı, buyruk döngüsünün getirme aşamasında okunacak buyruğun adresini sağlayarak programın hangi noktada yürütülmekte olduğunu belirler.

Program sayacı, saklı program kavramının doğrudan sonucudur. Buyrukların veriyle aynı bellekte durduğu bir makinede, sıradaki buyruğun nereden alınacağını gösteren bir işaretçi gerekir; program sayacı bu işi görür ve yürütmenin akışını temsil eden tek bir sayıya indirger.

Çalışma ilkesi

Program sayacının bir döngü boyunca aldığı değerler. Olağan akışta dörder artar; koşullu dallanma sağlandığında üzerine hedef adres yazılır.

Bir buyruk bellekten getirildikten sonra program sayacı, kendiliğinden bir sonraki buyruğun adresini gösterecek biçimde artırılır. Artış miktarı mimariye bağlıdır: sabit uzunlukta buyruk kullanan indirgenmiş buyruk kümeli mimarilerde her adımda sabit bir değer (çoğunlukla 4 bayt) eklenir; değişken uzunlukta buyruk kullanan mimarilerde ise artış, getirilen buyruğun uzunluğu kadardır. Böylece olağan akışta buyruklar bellekte sıralı olarak yürütülür.

Artırma işleminin buyruk getirildikten hemen sonra yapılmasının bir sonucu vardır: buyruk yürütülürken program sayacı artık o buyruğun değil, bir sonrakinin adresini tutar. Altyordam çağrılarında saklanan dönüş adresinin doğru yeri göstermesi bu davranıştan gelir; çağrı buyruğu yürütülürken program sayacında zaten çağrıdan sonraki buyruğun adresi durmaktadır.

Dallanma ve atlamalar

Programın akışını değiştiren buyruklar, program sayacına sıradaki adres yerine başka bir hedef adres yükler:

Bu buyrukların hepsi aynı işi yapar: program sayacının olağan artışını iptal edip yerine başka bir değer koyar. Donanımda bu, sıradaki adres ile hedef adres arasında seçim yapan bir çoklayıcıyla gerçeklenir.

Program sayacına göre adresleme

Aynı makine kodu iki ayrı taban adreste. Dallanma eklentisi buyruğun kendi adresine göre olduğundan ikisi de doğru hedefe gider.

Dallanma buyrukları hedefi çoğu zaman mutlak bir adres olarak değil, program sayacına eklenecek işaretli bir sayı olarak taşır. Buna program sayacına göre adresleme (İngilizce: PC-relative addressing) denir ve iki kazancı vardır.

Birincisi buyruk boyudur. Dallanmaların hedefi çoğunlukla yakındadır; birkaç yüz baytlık bir eklentiyi kodlamak, tam bir adresi kodlamaktan çok daha az bit ister. Sabit uzunluklu buyruk kullanan mimarilerde bu, dallanma buyruğunun tek bir sözcüğe sığmasını sağlar.

İkincisi konumdan bağımsızlıktır. Eklenti buyruğun kendi adresine göre hesaplandığından, kod bellekte nereye yerleştirilirse yerleştirilsin dallanma aynı hedefe gider. Aynı makine kodu farklı adreslerde değiştirilmeden çalışabilir; paylaşılan kitaplıkların her süreçte başka bir adrese eşlenebilmesi buna dayanır.

Eklentinin neye göre sayıldığı mimariden mimariye değişir. Kimi mimarilerde taban, dallanma buyruğunun kendi adresidir; kimilerinde ise artırılmış program sayacı, dolayısıyla bir sonraki buyruğun adresidir. Aradaki fark, elle yazılan çevirici kodunda kolayca yanlış hesaba yol açar.

Boru hattında program sayacı

Boru hattında her aşama kendi buyruğunun adresini taşır. Vurgulu çevrimde beş ayrı adres aynı anda canlıdır.

Boru hatlı bir işlemcide aynı anda birden çok buyruk işlenir ve her biri farklı bir aşamadadır. Bu durumda tek bir program sayacı değerinden söz edilemez: her aşama, o sırada işlediği buyruğun adresini kendisiyle birlikte taşımak zorundadır.

Adresin buyrukla birlikte taşınması gereksiz bir yük değildir. Bir kural dışı durum oluştuğunda hangi buyruğun hatalı olduğunun bilinmesi, dolayısıyla o buyruğun adresinin elde bulunması gerekir; dallanma çözüldüğünde yanlış öngörülen buyrukların atılıp doğru adresten yeniden başlanması da aynı bilgiyi ister.

Boru hattının bu davranışı kimi mimarilerin tanımına da yansımıştır. ARM'ın 32 bitlik sürümlerinde program sayacı okunduğunda, o anda yürütülen buyruğun adresi değil sekiz fazlası elde edilir. Bu sayı, ilk ARM işlemcilerindeki üç aşamalı boru hattında getirme biriminin ne kadar ilerlemiş olduğunu yansıtır ve sonradan mimarinin bir parçası olarak korunmuştur.

Öngörü ve sırasız yürütümde

Dallanma öngörüsü kullanan bir işlemci, dallanmanın sonucu belli olmadan sıradaki buyrukları getirmeye başlar. Bunun için program sayacını öngörülen hedefe göre ilerletir; öngörü yanlış çıkarsa getirilen buyruklar atılır ve program sayacı doğru adrese geri döndürülür.

Bu nedenle böyle bir işlemcide iki ayrı kavram bulunur. Öngörülen program sayacı getirme birimini yönlendirir ve yanılabilir; mimari program sayacı ise yalnızca gerçekten tamamlanan buyruklarla ilerler ve yazılımın gördüğü değerdir. Sırasız çalışan bir işlemcide buyruklar sırasız yürütülse de tamamlanma sırayla yapıldığından, mimari program sayacı her zaman tutarlı bir noktayı gösterir.

Ayrım, kesin kural dışı durumlar için zorunludur. Bir kesme geldiğinde işletim sisteminin gördüğü değer, öngörüyle ilerletilmiş olan değil, gerçekten tamamlanmış son buyruğun ardındaki adres olmalıdır; aksi durumda kesmeden dönüldüğünde program yanlış yerden sürerdi.

Genişlik ve başlangıç değeri

Program sayacının bit genişliği, işlemcinin doğrudan adresleyebileceği bellek alanının büyüklüğünü belirler. Birçok mimaride buyruklar belirli bir sınıra hizalı olduğundan program sayacının en düşük bitleri her zaman sıfır kalır; kimi tasarımlar bu bitleri hiç saklamaz ve yazmacı o kadar dar tutar.

İşlemci açıldığında veya sıfırlandığında program sayacı, önceden tanımlı bir başlangıç adresine (sıfırlama vektörü) yüklenir ve yürütme bu adresten başlar. Bu adres mimaride sabitlenmiştir, çünkü henüz çalışan bir program yoktur ve donanımın nereden başlayacağını kendiliğinden bilmesi gerekir.

Tarihçe

Program sayacı, buyrukların veriyle aynı bellekte saklandığı makinelerin ortaya çıkışıyla birlikte zorunlu hâle geldi. Buyrukların bir dış ortamdan sırayla okunduğu daha eski düzeneklerde böyle bir yazmaca gerek yoktu; sıra, ortamın kendisi tarafından belirleniyordu. Saklı program tasarımında ise sıradaki buyruğun bellekte nerede olduğunu gösteren bir değere gereksinim doğdu.

Erken makinelerde bu yazmaç tek bir adla anılmadı. Buyruk sayacı, denetim sayacı ve sıra denetim yazmacı gibi adlandırmalar kullanıldı; bugün yaygın olan program sayacı adı sonradan yerleşti. Ön panelinde yazmaç içeriklerini ışıklarla gösteren dönemin makinelerinde bu yazmaç, çalışan programın nerede olduğunu izlemenin başlıca yoluydu.

Yazmacın işlevi o günden bu yana değişmedi; değişen, çevresindeki donanımın karmaşıklığı oldu. Tek buyruğu tek seferde işleyen bir makinede program sayacı yalnızca artıp yeniden yükleniyordu. Boru hattı, dallanma öngörüsü ve sırasız yürütüm eklendikçe aynı kavram, aynı anda birden çok değeri ve bunlar arasında hangisinin gerçek olduğunu ayırt eden bir düzeni gerektirir duruma geldi.

Mimarilere göre adlandırma

Program sayacının adı ve gerçeklenişi mimariden mimariye değişir. Başlıca ayrım, yazmacın genel amaçlı yazmaç kümesinin bir üyesi olup olmadığıdır; üyeyse sıradan buyruklarla okunup yazılabilir, değilse yalnızca dallanma türü buyruklarla dolaylı olarak değiştirilebilir.

MimariAdıNotlar
x86IP, EIP, RIPKip genişliğine göre üç ad; genel amaçlı yazmaç değildir
ARM (32 bit)R15Genel amaçlı yazmaç kümesinin üyesi; okunduğunda sekiz fazlası elde edilir
ARM (64 bit)PCAyrı yazmaç; doğrudan yazılamaz
RISC-VpcYazmaç kümesinin dışında
MIPSPCAyrı yazmaç
SPARCPC ve nPCİki ayrı yazmaç; gecikmeli dallanma için sıradaki adres de tutulur
PDP-11R7Sekiz genel amaçlı yazmaçtan biri
68000PCAyrı yazmaç
PowerPCCIAKılavuzlarda "geçerli buyruk adresi" adıyla anılır
ItaniumIPBuyruk işaretçisi

Intel x86 ailesinde bu yazmaç buyruk işaretçisi (İngilizce: instruction pointer) olarak adlandırılır ve genişliğine göre ayrı adlar alır: 16 bitlik kipte IP, 32 bitlik kipte EIP, 64 bitlik kipte RIP. ARM'ın 32 bitlik sürümlerinde program sayacının genel amaçlı yazmaç kümesine dahil edilmesi, dallanmanın ayrı bir buyruk gerektirmeden sıradan bir yazmaç yazmasıyla yapılabilmesi anlamına gelir; bu esneklik karşılığında derleyici ve donanım için ek durumlar doğurur.

SPARC'ın iki sayaç tutması gecikmeli dallanmadan gelir. Dallanmadan sonraki buyruk her durumda yürütüldüğü için, donanımın hem o buyruğun hem de ondan sonra gidilecek yerin adresini elinde bulundurması gerekir.

Güvenlik

Altyordam çağrılarında saklanan dönüş adresi, program sayacının ileride alacağı değerdir. Bu değer bellekte, çoğu zaman yığında durduğu için yazılabilir; bir programda arabellek aşımı bulunduğunda saldırgan bu adresi değiştirerek yürütmeyi kendi seçtiği yere yönlendirebilir.

Saldırının gelişmiş biçimlerinde yeni kod yerleştirmeye bile gerek kalmaz; programda zaten bulunan kod parçalarının adresleri arka arkaya dizilerek istenen davranış elde edilir. Bu nedenle karşı önlemler doğrudan dönüş adresini korumaya yönelir: dönüş adresinin ayrı bir bellekte ikinci bir kopyasının tutulması ve dönüşte karşılaştırılması, ya da dallanma hedeflerinin yalnızca önceden belirlenmiş noktalar olabilmesi bu türdendir.

Hata ayıklamada

Bir programın nerede olduğunu gösteren değer program sayacıdır; hata ayıklayıcıların "şu satırdasınız" bilgisi, program sayacının kaynak koddaki karşılığını bulmasıyla üretilir. Kesme noktaları da aynı yazmaç üzerinden çalışır: hedef adresteki buyruk özel bir tuzak buyruğuyla değiştirilir, program sayacı oraya geldiğinde denetim hata ayıklayıcıya geçer.

Bir çökme sonrasında üretilen yığın izi, saklanmış dönüş adreslerinin zincirinden başka bir şey değildir. Her çerçevede bir önceki çağrının dönüş adresi durur; bu adreslerin sırayla çözülmesi, çökme anına kadar hangi işlevlerin çağrıldığını verir.

Ayrıca bakınız

Kaynakça

  1. 1 2 3 4 5 6 7 Patterson, David A.; Hennessy, John L. (2020). Computer Organization and Design RISC-V Edition: The Hardware/Software Interface (2 bas.). Morgan Kaufmann. ISBN 978-0128203316.
  2. 1 2 3 4 5 6 7 8 9 Tanenbaum, Andrew S.; Austin, Todd (2012). Structured Computer Organization (6 bas.). Pearson. ISBN 978-0132916523.
  3. 1 2 3 4 5 6 7 8 Hennessy, John L.; Patterson, David A. (2019). Computer Architecture: A Quantitative Approach (6 bas.). Morgan Kaufmann. ISBN 978-0128119051.
  4. 1 2 ARM Limited (2014). ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition. ARM.
  5. ↑ Intel Corporation (2023). Intel 64 and IA-32 Architectures Software Developer's Manual, Cilt 1. Intel.
  6. 1 2 Cowan, Crispin; Wagle, Perry; Pu, Calton (2000). "Buffer Overflows: Attacks and Defenses for the Vulnerability of the Decade". DARPA Information Survivability Conference and Exposition. ss. 119-129. doi:10.1109/DISCEX.2000.821514.