---
title: 'Komutlar ve Program Sayacı'
source: 'https://academia.sh/tr/kurslar/bilgisayarlar-nasil-calisir/komutlar-ve-program-sayaci'
course: 'Bilgisayarlar Nasıl Çalışır'
language: tr
updated: '2026-08-17T18:08:13+00:00'
license: 'CC BY-SA 4.0'
---

# Komutlar ve Program Sayacı

Komutların bit örüntüsü olarak kodlanması, getir–çöz–yürüt döngüsü ve program akışının oluşumu.

Önceki ders, verinin bellekte adreslenmiş baytlar olarak durduğunu kurdu. Komutlar da
aynı bellekte, aynı biçimde durur: bir komut, belirli bir kurala göre kodlanmış bit
örüntüsünden ibarettir. Program ile veri arasındaki ayrım donanımda değil, o baytlara
uygulanan yorumdadır.

Bu dersin sorusu şudur: işlemci, bellekteki bir bit örüntüsünü nasıl bir eyleme çevirir
ve bir sonraki eylemi nasıl belirler?

## Komut Kümesi

Her işlemci ailesinin tanımlı bir **komut kümesi (instruction set)** vardır: hangi
işlemlerin var olduğunu, her birinin hangi bit örüntüsüyle kodlandığını ve hangi
işlenenleri aldığını belirten sözleşme. Komut kümesi, donanım ile yazılım arasındaki
arayüzdür; aynı komut kümesini uygulayan iki farklı işlemci, aynı programı çalıştırabilir.

Tipik komut sınıfları azdır:

- **Veri taşıma** — bellekten yazmaca yükleme, yazmaçtan belleğe saklama.
- **Aritmetik ve mantık** — toplama, çıkarma, karşılaştırma, bit işlemleri.
- **Akış denetimi** — dallanma, alt yordam çağrısı ve dönüş.
- **Sistem** — kesme, ayrıcalık düzeyi değiştirme, işletim sistemi çağrısı.

Bir programlama dilindeki her yapı, sonunda bu sınıflardan komutlara indirgenir.

## Bir Komut Nasıl Kodlanır

Komut kodlaması, bit alanlarına bölünmüş bir örüntüdür. Alanlardan biri **işlem kodu
(opcode)**, hangi işlemin yapılacağını söyler; diğerleri işlenenleri belirtir.

Yapıyı somutlaştırmak için, yalnızca öğretim amacıyla tanımlanmış 32 bitlik bir kodlama
düşünün. Bu kodlama gerçek bir işlemciye ait değildir; alan yerleşimi her mimaride
farklıdır.

| Bit aralığı | Alan | Genişlik |
|---|---|---|
| 31–24 | işlem kodu | 8 bit |
| 23–16 | hedef yazmaç | 8 bit |
| 15–8 | birinci kaynak | 8 bit |
| 7–0 | ikinci kaynak | 8 bit |

Kursun ortak örneği bu kurala göre çözülürse:

$$
\texttt{0x41424344} \rightarrow \underbrace{\texttt{0x41}}_{\text{işlem}}\ \underbrace{\texttt{0x42}}_{\text{hedef}}\ \underbrace{\texttt{0x43}}_{\text{kaynak 1}}\ \underbrace{\texttt{0x44}}_{\text{kaynak 2}}
$$

`0x41` işlem kodunun "topla" anlamına geldiği varsayılırsa, komut şunu söyler: 67 ve 68
numaralı yazmaçların içeriğini topla, sonucu 66 numaralı yazmaca yaz.

Aynı otuz iki bit, bu konuya kadar dört kez yorumlandı: tam sayı, kayan noktalı sayı,
metin ve şimdi komut. Örüntüyü hangi yorumun karşılayacağına, işlemcinin o baytları
nereden okuduğu karar verir — komut olarak mı, veri olarak mı.

Sabit uzunluklu kodlamalar (her komut aynı genişlikte) çözme aşamasını basitleştirir.
Değişken uzunluklu kodlamalar ise sık kullanılan komutları daha az bayta sığdırarak
program boyutunu küçültür. İki yaklaşım da yaygındır ve seçim, mimarinin tasarım
önceliklerini yansıtır.

## Makine Dili ve Çevirici Dili

Bit örüntülerini elle yazmak hataya açıktır. **Çevirici dili (assembly)**, her komuta
okunabilir bir ad veren birebir gösterimdir:

```
    yukle   r1, [1000]     ; 1000 adresindeki değeri r1'e yükle
    yukle   r2, [1004]
    topla   r3, r1, r2     ; r3 = r1 + r2
    sakla   [1008], r3
```

Çevirici dili ile makine dili arasındaki ilişki neredeyse birebirdir: her satır bir
komuta çevrilir. Yüksek seviyeli dillerdeki bir satır ise onlarca komuta karşılık
gelebilir; bu çeviriyi derleyici yapar ve konunun son dersinde ele alınır.

## Getir–Çöz–Yürüt Döngüsü

İşlemci, açıldığı andan kapanana kadar tek bir döngüyü tekrarlar:

1. **Getir (fetch).** Program sayacının gösterdiği adresten komut okunur.
2. **Çöz (decode).** Bit alanları ayrıştırılır; işlem kodu ve işlenenler belirlenir.
3. **Yürüt (execute).** İşlem, aritmetik ve mantık birimi veya bellek birimi tarafından
   gerçekleştirilir.
4. **Sonucu yaz.** Üretilen değer hedef yazmaca veya belleğe yazılır.
5. Program sayacı bir sonraki komuta ilerletilir ve döngü baştan başlar.

**Program sayacı (program counter)**, bir sonraki komutun adresini tutan özel bir
yazmaçtır. Sıradan komutlarda her adımda komut genişliği kadar artar; program bu yüzden
"yukarıdan aşağı" akar.

Bu döngü, işlemcinin yaptığı her şeyin tanımıdır. Bir işletim sistemi, bir tarayıcı ya
da bir oyun arasındaki fark, döngüde değil, döngünün okuduğu komut dizisindedir.

## Adımların Örtüşmesi

Döngünün adımları farklı donanım birimlerini kullanır: getirme bellek arayüzünü, çözme
denetim birimini, yürütme aritmetik birimini meşgul eder. Her adımı sırayla beklemek, bu
birimlerin çoğunu her an boşta bırakır.

**Boru hattı (pipeline)** bu boşluğu kapatır: bir komut yürütülürken bir sonraki
çözülür, üçüncüsü getirilir. Tek bir komutun tamamlanma süresi değişmez; birim zamanda
tamamlanan komut sayısı artar.

Boru hattının bedeli dallanmadır. Koşullu dallanmada bir sonraki komutun adresi, koşul
hesaplanana kadar bilinmez; boru hattına hangi komutların alınacağı belirsizdir. İşlemci
bir tahminde bulunur ve tahmin yanlış çıkarsa hattaki komutları atar. Tahmin edilmesi güç
dallanmalar bu yüzden ölçülebilir bir maliyet taşır.

Bu, ilk konudaki bir gözlemi tekrarlar: komut sayısı, sürenin tek belirleyicisi
değildir.

## Akışın Değiştirilmesi

Program sayacına doğrudan yazılabilmesi, tüm denetim yapılarının kaynağıdır.

**Koşulsuz dallanma**, program sayacına yeni bir adres yazar; akış oradan devam eder.
**Koşullu dallanma** ise önce bir karşılaştırma sonucuna bakar. Karşılaştırma komutları,
sonucu bayrak bitlerine yazar — sonuç sıfır mı, negatif mi, taşma oldu mu. Koşullu
dallanma bu bayrakları okur ve program sayacını yalnızca koşul sağlanıyorsa değiştirir.

Yüksek seviyeli yapıların karşılığı böylece kurulur:

| Yapı | Komut karşılığı |
|---|---|
| `if` | Karşılaştır, koşul sağlanmıyorsa bloğun sonuna dallan |
| `while` | Koşulu sınayan dallanma + gövde sonunda başa dönen dallanma |
| Fonksiyon çağrısı | Dönüş adresini sakla, hedefe dallan; dönüşte saklanan adrese dallan |

Fonksiyon çağrısında dönüş adresinin nereye saklandığı, çağrı yığıtının işlevidir; yığıt
düzeni konunun son dersinde ele alınacaktır.

Aşağıdaki program, getir–çöz–yürüt döngüsünü öğretim amaçlı kodlama üzerinde canlandırır:

```python
ISLEM_ADLARI = {0x41: "topla", 0x42: "cikar", 0xFF: "dur"}


def coz(komut: int) -> tuple[str, int, int, int]:
    """32 bitlik komutu alanlarına ayırır."""
    islem  = (komut >> 24) & 0xFF
    hedef  = (komut >> 16) & 0xFF
    kaynak1 = (komut >> 8) & 0xFF
    kaynak2 = komut & 0xFF
    return ISLEM_ADLARI.get(islem, "bilinmeyen"), hedef, kaynak1, kaynak2


def calistir(bellek: list[int], yazmac: dict[int, int]) -> None:
    ps = 0                                   # program sayacı
    while ps < len(bellek):
        islem, hedef, k1, k2 = coz(bellek[ps])
        if islem == "dur":
            break
        if islem == "topla":
            yazmac[hedef] = yazmac.get(k1, 0) + yazmac.get(k2, 0)
        elif islem == "cikar":
            yazmac[hedef] = yazmac.get(k1, 0) - yazmac.get(k2, 0)
        ps += 1                              # bir sonraki komuta ilerle


print(coz(0x41424344))       # ('topla', 66, 67, 68)

bellek = [0x41424344, 0x42024344, 0xFF000000]
yazmac = {67: 10, 68: 4}
calistir(bellek, yazmac)
print(yazmac[66], yazmac[2]) # 14 6
```

`ps += 1` satırı, program sayacının sıradan ilerlemesidir. Bir dallanma komutu
eklenseydi, yaptığı tek şey bu değişkene farklı bir değer yazmak olurdu.

## Özet

- Komutlar da veriler gibi bellekte durur; ayrım, baytlara uygulanan yorumdadır.
- Komut kümesi, donanım ile yazılım arasındaki sözleşmedir ve az sayıda komut sınıfı
  içerir.
- Bir komut, işlem kodu ve işlenen alanlarına bölünmüş bir bit örüntüsüdür; alan
  yerleşimi mimariye özgüdür.
- İşlemci getir–çöz–yürüt döngüsünü sürekli tekrarlar; programlar arasındaki fark
  döngüde değil, okunan komut dizisindedir.
- Program sayacı bir sonraki komutun adresini tutar; koşullu ve koşulsuz dallanma bu
  yazmacı değiştirerek tüm denetim yapılarını üretir.

## Sonraki Adım

Döngünün her turu belleğe en az bir erişim gerektirir ve önceki derste görüldüğü gibi
ana bellek, işlemciye göre yüzlerce kat yavaştır. Sonraki ders, bu farkı kapatan
önbellek katmanını ve önbelleğin verimli çalışması için programın uyması gereken erişim
düzenini ele alacak.
