Bölüm 1: Programlama Dilleri
Giriş
Öğrenme Çıktıları
Makine dili, çevirici dil ve yüksek seviyeli diller arasındaki farkı açıklamak.
Bir komut biçimine göre ikili komutları kodlamak ve çözmek.
Etiket, komut, işlenen, yönerge kavramlarını tanımak; sistem çağrısı yapan kısa programları okumak.
Aynı programın x86, 68000, ARM, PowerPC ve farklı işletim sistemlerinde neden farklı yazıldığını açıklamak.
Derleyici, bağlayıcı, yorumlayıcı ve JIT kavramlarını karşılaştırmak.
Aynı algoritmayı farklı dillerde ve 8086 assembly ile izlemek.
Yazılım
Yazılım
- Bilgisayar donanımını düzgün, koordineli ve istenen şekilde çalıştırır.
- İşletim sistemi
- bilgisayarın temel yazılımıdır,
- donanımı yönetir, diğer yazılımların çalışmasını denetler.
- Programlama dilleri
- yazılım geliştirmek için icat edilmiştir,
- farklı alanlara yönelik çok sayıda dil vardır.
- Programlama dillerinin evrimi, bilgisayar teknolojisindeki önemli gelişmeleri yansıtır.
Yazılım
Programlama Dilleri: Seviyeler
- Makine dilleri: işlemcinin doğrudan çalıştırdığı 0 ve 1'ler.
- Çevirici diller: makine komutlarının sembolik (anımsatıcı) yazımı.
- Yüksek seviyeli diller
- derlenen: önce makine diline çevrilir, sonra çalışır;
- yorumlanan: çalışma anında satır satır işlenir.
Yazılım · Adım adım
Aynı İşlem Üç Seviyede: x = a + b
MOV AX, [a] ; a'yı AX yazmacına yükle ADD AX, [b] ; AX = AX + b MOV [x], AX ; sonucu x'e yazHer satır tek bir makine komutuna karşılık gelir.
A1 00 02 ; MOV AX, [0200h] 03 06 02 02 ; ADD AX, [0202h] A3 04 02 ; MOV [0204h], AXAdresler bellekte düşük bayt önce (little-endian) saklanır: 0200h →
00 02.Makine Dili
Makine Dilleri
- 0 ve 1'lerden oluşan en alt seviyeli dildir; işlemci yalnızca bunu anlar.
- Tamamen işlemciye ve donanıma bağımlıdır: 8086 için yazılan makine kodu ARM'da çalışmaz.
- İlk genel amaçlı elektronik bilgisayarlardan ENIAC (1945), kablolar ve anahtarlarla doğrudan donanım üzerinde programlanıyordu.
- Günümüzde
- her işlemci ailesinin kendine özgü bir makine dili (komut kümesi) vardır,
- okuması ve yazması pratik olmadığı için doğrudan kullanılmaz.
- Çevirici diller makine diline bağımlılığı azaltır ve daha insan dostu bir programlama sağlar.
B0 05 baytları “AL'ye 5 yükle” demektir. Aynı iş ARM'da 32 bitlik tamamen farklı bir sözcükle kodlanır.Makine Dili
Örnek Bir Makine Dili Tasarımı
| İşlem kodu | Anlamı |
|---|---|
0000 | HALT: programı durdur |
0001 | ADD: toplama |
0010 | SUB: çıkarma |
0011 | AND: mantıksal VE |
0100 | OR: mantıksal VEYA |
- Komutlar 8 bitliktir.
- 4 yazmaç: R0 =
00, R1 =01, R2 =10, R3 =11. - Anlam: hedef ← hedef işlem kaynak.
- 4 bitlik işlem kodu en çok 24 = 16 işlem tanımlayabilir; burada 5'i kullanılıyor.
0001 10 11 → ADD R2, R3 → R2 ← R2 + R3Makine Dili
Örnek Program: Alanları Ayırmak
| Makine kodu | İşlem | Hedef | Kaynak | Anlamı |
|---|---|---|---|---|
0001 0001 | ADD | R0 | R1 | R0 ← R0 + R1 |
0011 1011 | AND | R2 | R3 | R2 ← R2 AND R3 |
0100 0110 | OR | R1 | R2 | R1 ← R1 OR R2 |
0000 0000 | HALT | — | — | programı durdur |
Onaltılık karşılıkları: 11h, 3Bh, 46h, 00h.
Makine Dili · Kodu adım adım çalıştır
Kod İzleme: Örnek Makine Programı
Başlangıç değerleri (örnek). PC = 0: ilk komut getirilecek.
ADD R0, R1: 5 + 3 = 8 → R0. Kaynak (R1) değişmez.
AND R2, R3: 1100 AND 1010 = 1000 → R2 = 8. Yalnızca iki tarafta da 1 olan bit kalır.
OR R1, R2: 0011 OR 1000 = 1011 → R1 = 11.
HALT: işlemci durur. Sonuç: R0 = 8, R1 = 11, R2 = 8, R3 = 10.
0001 0001 ; ADD R0, R1 → R0 ← R0 + R1 0011 1011 ; AND R2, R3 → R2 ← R2 AND R3 0100 0110 ; OR R1, R2 → R1 ← R1 OR R2 0000 0000 ; HALT
Makine Dili · Etkileşimli
Kodlayıcı ve Çözücü
Üstteki seçimleri değiştir (kodlama) ya da sağdaki kutuya 8 bit yaz (çözme). 0101–1111 işlem kodları bu tasarımda tanımsızdır.
Makine Dili
Makine Dili: Artılar ve Eksiler
Artılar
- Çeviri gerekmez; işlemci doğrudan çalıştırır.
- Donanım üzerinde tam denetim.
- En küçük ve (doğru yazılırsa) en hızlı kod.
Eksiler
- Okuması, yazması ve hata ayıklaması çok zor.
- Adresler elle hesaplanır; araya bir komut eklemek tüm atlama adreslerini bozar.
- Taşınabilir değil: her işlemci için baştan yazılır.
- Tek bir bit hatası programı tamamen değiştirir.
Çevirici Diller
Çevirici (Assembly) Diller
- Her makine komutu, akılda kalır bir anımsatıcıyla (mnemonic) yazılır:
10110000 00000101yerineMOV AL, 5. - Farklı işlemci mimarilerine ve komut kümelerine göre tasarlanır: Intel x86, Motorola 68000, ARM, PIC, AVR için ayrı çevirici diller vardır.
- Mikrodenetleyicilere özel çevirici diller gömülü sistemlerde ve elektronik uygulamalarda sıkça kullanılır.
- Bir işlemci ailesi içinde uyumu sağlar ve donanım özelliklerinden en iyi şekilde yararlanmayı amaçlar.
- Kaynak kodu makine diline çeviren programa çevirici (assembler) denir.
Çevirici Diller
Kaynak Koddan Çalışan Programa
Çeviricinin liste (listing) çıktısı, her satırın adresini ve makine kodunu yan yana gösterir:
Adres Makine kodu Kaynak 0100 B4 09 mov ah, 09h 0102 BA 0C 01 mov dx, offset mesaj 0105 CD 21 int 21h 0107 B8 00 4C mov ax, 4C00h 010A CD 21 int 21h 010C 4D 65 72 ... mesaj db 'Merhaba!$'
emu8086 bu adımları tek tuşla yapar ve COM/EXE dosyasını doğrudan üretir.
Çevirici Diller
Bir Assembly Satırının Yapısı
| Öğe | Görevi | Örnek |
|---|---|---|
| Etiket | bir adrese isim verir; atlama ve veri hedefi | dongu:, mesaj |
| Anımsatıcı | makine komutunun adı | MOV, ADD, JMP, INT |
| İşlenenler | yazmaç, sabit ya da bellek; 8086'da önce hedef, sonra kaynak | AX, 5 · [BX], AL |
| Yönerge (directive) | makine kodu üretmez, çeviriciye talimat verir | ORG 100h, DB, SECTION, EQU |
| Yorum | ; ile başlar (ARM GNU'da @, PPC'de #) | ; açıklama |
Çevirici Diller
Çeviriciler ve Sözdizimleri
| Çevirici | Sözdizimi · kullanım |
|---|---|
| MASM | Intel · Microsoft, Windows |
| TASM | Intel · Borland, DOS |
| NASM | Intel · açık kaynak, çok platform |
| GAS (as) | AT&T · GNU/Linux, gcc |
| emu8086 | Intel (MASM benzeri) · 8086 benzetimcisi, bu ders |
Aynı komut, iki yazım
; Intel: hedef, kaynak mov eax, 5 add eax, [ebx+4] # AT&T: kaynak, hedef movl $5, %eax addl 4(%ebx), %eax
AT&T'de yazmaçlar %, sabitler $ ile yazılır; boyut komut sonekinde (l = 32 bit) belirtilir.
Çevirici Diller · Kodu adım adım çalıştır
x86 Assembly: Linux (32 bit, NASM)
Veri bölümü: dizge ve sonuna satır sonu (10). len, $ - hello ile 16 olarak hesaplanır.
Program _start'tan başlar. EAX = 4: sys_write sistem çağrısı numarası.
EBX = 1: yazılacak dosya tanıtıcısı stdout (ekran).
ECX = dizgenin adresi (içeriği değil).
EDX = 16 (10h): yazılacak bayt sayısı.
int 0x80: çekirdek çağrılır, metin yazılır. Dönüşte EAX = yazılan bayt sayısı (16).
EAX = 1: sys_exit.
xor ebx, ebx: bir sayı kendisiyle XOR'lanınca 0 olur → çıkış kodu 0 (başarı). mov ebx, 0'dan kısadır.
Çekirdek süreci 0 çıkış koduyla sonlandırır; bu çağrı geri dönmez.
section .data hello db 'Merhaba, Linux!', 10 len equ $ - hello ; = 16 bayt section .text global _start _start: mov eax, 4 ; sys_write mov ebx, 1 ; stdout mov ecx, hello ; dizgenin adresi mov edx, len ; bayt sayısı int 0x80 ; çekirdeği çağır mov eax, 1 ; sys_exit xor ebx, ebx ; çıkış kodu 0 int 0x80
Kaynakta sabit 15 bayt yazılıyordu; “Merhaba, Dünya!” metninde ü harfi UTF-8'de 2 bayt olduğundan (16 bayt) “!” kesiliyordu. equ $ - hello uzunluğu çeviriciye hesaplatır.
Çevirici Diller
Sistem Çağrısı Nasıl Çalışır?
| Ortam | Çağrı | Hizmet numarası | Parametreler |
|---|---|---|---|
| Linux 32 bit | int 0x80 | EAX (4 = write, 1 = exit) | EBX, ECX, EDX |
| Linux 64 bit | syscall | RAX (1 = write, 60 = exit) | RDI, RSI, RDX |
| MS-DOS | int 21h | AH (09h = yaz, 4Ch = çık) | DX, AL … |
| BIOS | int 10h | AH (0Eh = karakter yaz) | AL, BH … |
Çevirici Diller · Kodu adım adım çalıştır
x86 Assembly: DOS (emu8086, COM)
org 100h: COM programı kesimin 100h adresine yüklenir (önceki 256 bayt PSP). CS = DS = ES = SS.
AH = 09h: DOS'un “$ ile biten dizgeyi yaz” hizmeti.
lea dx, mesaj: DS:DX dizgenin adresini gösterir. Kod 13 bayt (0100h–010Ch) olduğundan mesaj 010Dh'de.
int 21h: DOS, '$' görene kadar karakterleri ekrana yazar ('$' yazılmaz).
AX = 4C00h: AH = 4Ch “programı sonlandır”, AL = 00h çıkış kodu.
Program biter, denetim DOS'a döner. Veri kodun arkasında olduğu için işlemci hiçbir zaman veriyi komut sanıp çalıştırmaz.
org 100h ; COM programı mov ah, 09h ; DOS 09h: dizge yaz lea dx, mesaj ; DS:DX = adres int 21h ; DOS hizmetini çağır mov ax, 4C00h ; DOS 4Ch: sonlandır int 21h mesaj db 'Merhaba, DOS!$'
Kaynaktaki sürümde dizge 0 ile bitiyordu ve veri kodun önündeydi; 09h hizmeti '$' sonlandırıcı bekler ve öndeki veri komut gibi çalıştırılırdı. AL'nin de sıfırlanması için mov ax, 4C00h kullanıldı.
Çevirici Diller
x86 Assembly: Windows (Win32 API, NASM)
extern MessageBoxA ; user32.dll extern ExitProcess ; kernel32.dll section .data mesaj db 'Merhaba, Windows!', 0 section .text global _start _start: push 0 ; uType = MB_OK push mesaj ; lpCaption (başlık) push mesaj ; lpText (metin) push 0 ; hWnd = NULL call MessageBoxA push 0 ; uExitCode = 0 call ExitProcess
- Sistem çağrısı yok: işletim sistemi hizmetleri DLL fonksiyonları olarak çağrılır.
- Parametreler yığına sağdan sola itilir: C'deki
MessageBoxA(hWnd, lpText, lpCaption, uType). - stdcall: yığını çağrılan fonksiyon temizler.
- Dizgeler 0 ile biter (C dizgesi).
- Bağlarken süslenmiş ad gerekebilir:
_MessageBoxA@16(16 = parametre baytı).
Çevirici Diller · Kodu adım adım çalıştır
Kod İzleme: Parametreler Yığına
Başlangıç: ESP = 0012FF80h (örnek değer). Yığın düşük adreslere doğru büyür.
push 0: ESP 4 azalır, son parametre (uType) önce itilir.
push mesaj: başlık dizgesinin adresi itilir.
push mesaj: metin dizgesinin adresi.
push 0: ilk parametre (hWnd) en son itilir → yığının tepesinde. Parametreler sağdan sola itilir.
call MessageBoxA: dönüş adresi itilir ve fonksiyona atlanır; ekranda ileti kutusu açılır.
Kullanıcı Tamam'a basınca fonksiyon ret 16 ile döner: stdcall'da yığını çağrılan temizler, ESP yeniden 0012FF80h. EAX = 1 (IDOK).
push 0 + call ExitProcess: süreç 0 çıkış koduyla sonlanır; bu çağrı geri dönmez.
extern MessageBoxA extern ExitProcess section .data mesaj db 'Merhaba...', 0 section .text global _start _start: push 0 ; uType push mesaj ; lpCaption push mesaj ; lpText push 0 ; hWnd call MessageBoxA push 0 ; uExitCode call ExitProcess
Çevirici Diller
Motorola 68000 Assembly: Amiga
move.l 4.w,a6 ; a6 = ExecBase lea dosname(pc),a1 ; kütüphane adı moveq #0,d0 ; herhangi bir sürüm jsr -552(a6) ; OpenLibrary() tst.l d0 beq.s cik ; açılamadı → çık move.l d0,a6 ; a6 = DOSBase jsr -60(a6) ; Output() → d0 move.l d0,d1 ; dosya tanıtıcısı move.l #mesaj,d2 ; dizgenin adresi moveq #16,d3 ; bayt sayısı jsr -48(a6) ; Write(d1,d2,d3) move.l a6,a1 move.l 4.w,a6 jsr -414(a6) ; CloseLibrary() cik moveq #0,d0 ; dönüş kodu 0 rts dosname dc.b 'dos.library',0 mesaj dc.b 'Merhaba, Amiga!',10
- 8 veri (
d0–d7) ve 8 adres (a0–a7) yazmacı; kaynak, hedef sırası. - Boyut soneki:
.b,.w,.l; sabitler#ile. - Hizmetler kütüphane tabanından negatif uzaklıkla (
-48(a6)) çağrılır. - Kütüphane açılır, kullanılır, kapatılır.
Kaynaktaki sürüm A6'ya 14 ve 20 sabitlerini yükleyip oraya atlıyordu (geçersiz adres) ve ayrıcalıklı STOP komutuyla bitiyordu; AmigaOS'un exec/dos kütüphane çağrılarıyla düzeltildi.
Çevirici Diller
ARM Assembly: Linux (32 bit, GNU as)
.data mesaj: .ascii "Merhaba, ARM!\n" uzun = . - mesaj @ 14 bayt .text .global _start _start: mov r7, #4 @ sys_write mov r0, #1 @ stdout ldr r1, =mesaj @ dizgenin adresi mov r2, #uzun @ bayt sayısı svc #0 @ çekirdeği çağır mov r7, #1 @ sys_exit mov r0, #0 @ çıkış kodu svc #0
- RISC: 16 yazmaç (
r0–r15), sabit 32 bitlik komutlar. - Hizmet numarası r7'de, parametreler r0–r2'de.
- Çekirdeğe geçiş:
svc #0(eski adıswi). - Bellekten yalnızca
ldr/strile okunur/yazılır.
Düzeltmeler: GNU as'ta db değil .ascii kullanılır; “Merhaba, ARM!” 13 karakterdir, kaynaktaki 15 bayt dizgenin dışını yazıyordu.
Çevirici Diller
PowerPC (PPC) Assembly: Linux (32 bit)
.data mesaj: .ascii "Merhaba, PowerPC!\n" uzun = . - mesaj # 18 bayt .text .globl _start _start: li 0, 4 # r0 = sys_write li 3, 1 # r3 = stdout lis 4, mesaj@ha # r4 = adres (üst) addi 4, 4, mesaj@l # + alt yarı li 5, uzun # r5 = bayt sayısı sc # çekirdeği çağır li 0, 1 # r0 = sys_exit li 3, 0 # r3 = çıkış kodu sc
- RISC: 32 genel yazmaç; GNU as'ta yazmaçlar düz sayıyla yazılır (
3= r3). - Hizmet numarası r0'da, parametreler r3, r4, r5'te; geçiş
sc. - 32 bitlik adres, 16 bitlik iki parçada yüklenir (
@ha,@l).
Kaynaktaki sürümde hizmet numarası r4'e, adres olarak yığın işaretçisi (r1) r5'e konuyordu; Linux PPC çağrı kuralına göre düzeltildi.
Çevirici Diller
Aynı “Merhaba”, Altı Ortam
| Ortam | İşlemci | OS'a geçiş | Hizmet no. | Parametreler | Dizge sonu |
|---|---|---|---|---|---|
| Linux | x86 (32) | int 0x80 | EAX | EBX, ECX, EDX | uzunluk verilir |
| DOS | 8086 | int 21h | AH | DX (adres) | '$' |
| Windows | x86 (32) | call DLL | fonksiyon adı | yığın | 0 |
| AmigaOS | 68000 | jsr -48(a6) | kütüphane uzaklığı | d1, d2, d3 | uzunluk verilir |
| Linux | ARM | svc #0 | r7 | r0, r1, r2 | uzunluk verilir |
| Linux | PowerPC | sc | r0 | r3, r4, r5 | uzunluk verilir |
Yüksek Seviyeli Diller
Yüksek Seviyeli Diller
- Kaynak kod önceden makine diline çevrilir.
- Hataların çoğu derleme sırasında yakalanır.
- Performans avantajı sağlar.
- Aşamalar: derleme (compiler) ve bağlama (linker).
- Çıktı belirli bir işlemci + işletim sistemine özgüdür.
- Kaynak kod çalışma anında yorumlayıcı tarafından işlenir.
- Hızlı geliştirme ve deneme imkânı sağlar.
- Kaynak kod platformdan bağımsızdır: yorumlayıcı olan her yerde çalışır.
- Hatalar ancak ilgili satır çalışınca ortaya çıkabilir.
- Genelde daha yavaştır.
Yüksek Seviyeli Diller · Adım adım
Derleme Süreci (C, gcc)
#include ve #define açılır → tekcift.i (gcc -E)tekcift.s (gcc -S)tekcift.o (gcc -c)printf/scanf gibi kütüphane kodlarıyla birleştirilir → çalıştırılabilir tekcift / tekcift.exemain'e atlar.Tek komutla: gcc tekcift.c -o tekcift. Ara assembly'yi görmek için gcc -S -masm=intel tekcift.c.
Yüksek Seviyeli Diller · Derlenen
Derlenen Diller
- Kaynak kod çalışmadan önce derleyici tarafından bütünüyle incelenir.
- Derlenmiş kod doğrudan işlemcide çalıştığı için daha hızlıdır.
- Tip ve sözdizimi hataları derleme aşamasında tespit edilir.
Yüksek Seviyeli Diller · Kodu adım adım çalıştır
Görev: 1'den n'ye Tek/Çift — C
Bütün örnek programlar aynı işi yapar: bir sayı okur, 1'den o sayıya kadar her sayının tek mi çift mi olduğunu yazar.
Kullanıcı 3 girer. scanf'e değişkenin adresi (&number) verilir.
Döngü başlar: i = 1, koşul 1 ≤ 3 doğru.
1 % 2 = 1 ≠ 0 → else dalı: “tek”.
i++ → 2; 2 ≤ 3 doğru.
2 % 2 = 0 → “çift”.
i = 3; 3 ≤ 3 doğru.
3 % 2 = 1 → “tek”.
i = 4; 4 ≤ 3 yanlış → döngü biter.
return 0: işletim sistemine “başarılı” çıkış kodu.
#include <stdio.h> int main() { int number; printf("Bir sayi girin: "); scanf("%d", &number); for (int i = 1; i <= number; i++) { if (i % 2 == 0) { printf("%d sayisi bir cift sayidir.\n", i); } else { printf("%d sayisi bir tek sayidir.\n", i); } } return 0; }
Yüksek Seviyeli Diller · Derlenen
C++
#include <iostream> int main() { int number; std::cout << "Bir sayi girin: "; std::cin >> number; for (int i = 1; i <= number; i++) { if (i % 2 == 0) { std::cout << i << " sayisi bir cift sayidir." << std::endl; } else { std::cout << i << " sayisi bir tek sayidir." << std::endl; } } return 0; }
- C'nin üst kümesi; sınıflar, şablonlar, istisnalar.
- G/Ç için akışlar:
std::cout <<yazar,std::cin >>okur. - Derleme:
g++ tekcift.cpp -o tekcift std::endlsatır sonu ekler ve tamponu boşaltır; çok satırda'\n'daha hızlıdır.
Yüksek Seviyeli Diller · Derlenen (ara koda)
C#
using System; class Program { static void Main() { Console.Write("Bir sayi girin: "); int number = int.Parse(Console.ReadLine()); for (int i = 1; i <= number; i++) { if (i % 2 == 0) { Console.WriteLine($"{i} sayisi bir cift sayidir."); } else { Console.WriteLine($"{i} sayisi bir tek sayidir."); } } } }
- .NET platformu; IL ara diline derlenir, CLR çalışırken JIT ile makine koduna çevirir.
$"{i} …": dizge içine değer yerleştirme (interpolation).- Çalıştırma:
dotnet run int.Parsesayı olmayan girdide istisna fırlatır;int.TryParsedaha güvenlidir.
Yüksek Seviyeli Diller · Derlenen (bytecode)
Java
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.print("Bir sayi girin: "); int number = scanner.nextInt(); for (int i = 1; i <= number; i++) { if (i % 2 == 0) { System.out.println(i + " sayisi bir cift sayidir."); } else { System.out.println(i + " sayisi bir tek sayidir."); } } } }
javac→ platformdan bağımsız bytecode (.class) → JVM'de JIT.- “Bir kez yaz, her yerde çalıştır.”
- Çalıştırma:
javac Main.javavejava Main - Her şey bir sınıf içinde; dosya adı =
publicsınıf adı.
Yüksek Seviyeli Diller · Derlenen
Go
package main import "fmt" func main() { var number int fmt.Print("Bir sayi girin: ") fmt.Scan(&number) for i := 1; i <= number; i++ { if i%2 == 0 { fmt.Printf("%d sayisi bir cift sayidir.\n", i) } else { fmt.Printf("%d sayisi bir tek sayidir.\n", i) } } }
- Doğrudan makine koduna derlenir; tek, bağımsız çalıştırılabilir dosya.
- Çöp toplayıcı ve hafif iş parçacıkları (goroutine).
- Çalıştırma:
go run tekcift.go - Koşul ve döngülerde parantez yok;
:=tipi çıkarır.
Yüksek Seviyeli Diller · Derlenen
Rust
use std::io; fn main() { let mut input = String::new(); println!("Bir sayi girin:"); io::stdin().read_line(&mut input) .expect("okuma hatasi"); let number: i32 = input.trim().parse() .expect("cevirme hatasi"); for i in 1..=number { if i % 2 == 0 { println!("{} sayisi bir cift sayidir.", i); } else { println!("{} sayisi bir tek sayidir.", i); } } }
- Çöp toplayıcı olmadan bellek güvenliği: sahiplik (ownership) kuralları derleyicide denetlenir.
- Değişkenler varsayılan olarak değiştirilemez;
mutgerekir. 1..=number: üst sınır dahil aralık.- Çalıştırma:
rustc tekcift.rsya dacargo run
Yüksek Seviyeli Diller · Derlenen
Fortran
program Main implicit none integer :: number, i write(*,*) 'Bir sayi girin:' read(*,*) number do i = 1, number if (mod(i, 2) == 0) then write(*,*) i, ' sayisi bir cift sayidir.' else write(*,*) i, ' sayisi bir tek sayidir.' end if end do end program Main
- İlk yaygın yüksek seviyeli dil: FORmula TRANslation.
- Bilimsel hesaplamada hâlâ yaygın (hava tahmini, fizik).
implicit none: tüm değişkenler açıkça tanımlanmalı.- Çalıştırma:
gfortran tekcift.f90 -o tekcift write(*,*)serbest biçim yazar; sayıların önünde boşluk görülebilir.
Yüksek Seviyeli Diller · Derlenen
Ada
with Ada.Text_IO; use Ada.Text_IO; with Ada.Integer_Text_IO; use Ada.Integer_Text_IO; procedure Main is Number : Integer; begin Put ("Bir sayi girin: "); Get (Number); for I in 1 .. Number loop Put (I, Width => 0); if I mod 2 = 0 then Put_Line (" sayisi bir cift sayidir."); else Put_Line (" sayisi bir tek sayidir."); end if; end loop; end Main;
- Güçlü tip denetimi; havacılık ve savunma yazılımı.
- Çalıştırma:
gnatmake main.adb - Düzeltme: tamsayı
Get/PutiçinAda.Integer_Text_IOgerekir; kaynaktakiPut'lar satır sonu eklemediği için tüm çıktı tek satırda kalıyordu →Put_Line.
Yüksek Seviyeli Diller · Yorumlanan
Yorumlanan Diller
- Kaynak kod çalışma anında yorumlanır; ayrı bir derleme adımı yoktur.
- Hızlı geliştirme ve deneme (etkileşimli kabuk, REPL).
Yüksek Seviyeli Diller · Yorumlanan
Python
# Kullanıcıdan girdi alma number = int(input("Bir sayi girin: ")) # 1'den number'a kadar sayıları kontrol et for i in range(1, number + 1): if i % 2 == 0: print(f"{i} sayisi bir cift sayidir.") else: print(f"{i} sayisi bir tek sayidir.")
- Bloklar süslü parantezle değil girintiyle belirlenir.
range(1, number + 1): üst sınır dahil değildir, bu yüzden +1.inputmetin döndürür;int(...)sayıya çevirir.- Çalıştırma:
python tekcift.py - Dinamik tipli: değişkenin tipi çalışırken belirlenir.
Yüksek Seviyeli Diller · Yorumlanan (JIT)
JavaScript
// Kullanıcıdan girdi alma let number = Number(prompt("Bir sayi girin:")); // 1'den number'a kadar sayıları kontrol et for (let i = 1; i <= number; i++) { if (i % 2 === 0) { console.log(i + " sayisi bir cift sayidir."); } else { console.log(i + " sayisi bir tek sayidir."); } }
- Tarayıcıların dili; Node.js ile sunucuda da çalışır.
- Modern motorlar (V8) kodu JIT ile makine koduna çevirir.
promptmetin döndürür;Number(...)ile çevirmek güvenlidir (kaynakta çevrilmeden karşılaştırılıyordu).===: tip dönüştürmeden eşitlik.
Yüksek Seviyeli Diller · Yorumlanan
Ruby
# Kullanıcıdan girdi alma print "Bir sayi girin: " number = gets.chomp.to_i # 1'den number'a kadar sayıları kontrol et for i in 1..number do if i % 2 == 0 puts "#{i} sayisi bir cift sayidir." else puts "#{i} sayisi bir tek sayidir." end end
- Her şey bir nesnedir:
gets.chomp.to_iart arda metot çağrısıdır. chompsatır sonunu atar,to_itamsayıya çevirir.1..number: üst sınır dahil aralık."#{i}": dizge içine değer yerleştirme.- Çalıştırma:
ruby tekcift.rb
Yüksek Seviyeli Diller · Yorumlanan
PHP
<?php // Kullanıcıdan girdi alma echo "Bir sayi girin: "; $number = (int) trim(fgets(STDIN)); // 1'den number'a kadar sayıları kontrol et for ($i = 1; $i <= $number; $i++) { if ($i % 2 == 0) { echo $i . " sayisi bir cift sayidir.\n"; } else { echo $i . " sayisi bir tek sayidir.\n"; } } ?>
- Sunucu tarafı web dili; HTML içine gömülebilir.
- Değişkenler
$ile başlar;.dizge birleştirir. fgets(STDIN)komut satırından bir satır okur;trimsatır sonunu atar.- Çalıştırma:
php tekcift.php
Yüksek Seviyeli Diller · Yorumlanan
Perl
use strict; use warnings; # Kullanıcıdan girdi alma print "Bir sayi girin: "; my $number = <STDIN>; chomp $number; # 1'den number'a kadar sayıları kontrol et for my $i (1..$number) { if ($i % 2 == 0) { print "$i sayisi bir cift sayidir.\n"; } else { print "$i sayisi bir tek sayidir.\n"; } }
- Metin işleme ve sistem yönetimi; güçlü düzenli ifadeler.
<STDIN>bir satır okur,chompsatır sonunu atar.- Çift tırnaklı dizgede
$idoğrudan değerle değiştirilir. use strict; use warnings;yaygın hataları yakalar.- Çalıştırma:
perl tekcift.pl
Yüksek Seviyeli Diller · Yorumlanan
MATLAB
% Kullanıcıdan girdi alma number = input('Bir sayi girin: '); % 1'den number'a kadar sayıları kontrol et for i = 1:number if mod(i, 2) == 0 fprintf('%d sayisi bir cift sayidir.\n', i); else fprintf('%d sayisi bir tek sayidir.\n', i); end end
- Matris tabanlı sayısal hesaplama; mühendislikte, özellikle sinyal işleme ve denetimde yaygın.
1:number: 1, 2, …, number vektörü.- Satır sonundaki
;sonucun ekrana basılmasını engeller. - Ücretsiz uyumlu alternatif: GNU Octave.
Yüksek Seviyeli Diller
Aynı Program, On Dört Dil
| Dil | Model | Döngü başlığı | Kalan | Yazdırma |
|---|---|---|---|---|
| C | derlenen | for (int i = 1; i <= n; i++) | i % 2 | printf |
| C++ | derlenen | for (int i = 1; i <= n; i++) | i % 2 | std::cout << |
| C# | IL + JIT | for (int i = 1; i <= n; i++) | i % 2 | Console.WriteLine |
| Java | bytecode + JIT | for (int i = 1; i <= n; i++) | i % 2 | System.out.println |
| Go | derlenen | for i := 1; i <= n; i++ | i%2 | fmt.Printf |
| Rust | derlenen | for i in 1..=n | i % 2 | println! |
| Fortran | derlenen | do i = 1, n | mod(i, 2) | write(*,*) |
| Ada | derlenen | for I in 1 .. N loop | I mod 2 | Put_Line |
| Python | yorumlanan | for i in range(1, n + 1): | i % 2 | print |
| JavaScript | yorumlanan/JIT | for (let i = 1; i <= n; i++) | i % 2 | console.log |
| Ruby | yorumlanan | for i in 1..n do | i % 2 | puts |
| PHP | yorumlanan | for ($i = 1; $i <= $n; $i++) | $i % 2 | echo |
| Perl | yorumlanan | for my $i (1..$n) | $i % 2 | print |
| MATLAB | yorumlanan/JIT | for i = 1:n | mod(i, 2) | fprintf |
Yüksek Seviyeli Diller
Derlenen, Yorumlanan, Hibrit
| Ölçüt | Derlenen | Yorumlanan | Hibrit (bytecode + JIT) |
|---|---|---|---|
| Çeviri zamanı | çalışmadan önce, bir kez | her çalıştırmada | önce ara koda, sonra çalışırken |
| Hız | en yüksek | en düşük | yüksek (ısındıktan sonra) |
| Dağıtılan | makine kodu | kaynak kod | ara kod (.class, .dll) |
| Taşınabilirlik | her platform için yeniden derle | yorumlayıcı olan her yer | sanal makine olan her yer |
| Hata yakalama | çoğu derlemede | çoğu çalışırken | tip hataları derlemede |
| Örnek | C, C++, Go, Rust, Fortran, Ada | Python, Ruby, PHP, Perl, MATLAB | Java, C#, JavaScript (V8) |
Köprü · Kodu adım adım çalıştır
Aynı Görev 8086 Assembly ile (n = 3)
CX sayaç (i) olarak kullanılır: i = 1. n = 3 sabit (okuma işlemi sonraki bölümlerde).
cmp cx, 3: 1 − 3 hesaplanır (sonuç saklanmaz) → ZF=0, CF=1 (ödünç). ja yalnız CF=0 ve ZF=0 iken atlar → atlamaz.
DL = 1 + 30h = 31h: rakam 1'in ASCII kodu. ADD bayrakları günceller: CF=0.
DOS 02h hizmeti DL'deki karakteri yazar.
test cl, 1: 1 AND 1 = 1 ≠ 0 → ZF=0 → jnz tek atlar. (i % 2 yerine en düşük bit.)
DX = tek_m dizgesinin adresi; 09h hizmeti '$'a kadar yazar. 0Dh, 0Ah satır başı + satır sonudur.
inc cx → 2 (INC, CF'yi değiştirmez); döngü başına dönülür.
2 − 3: CF=1 → devam.
DL = 32h ('2') yazılır.
2 AND 1 = 0 → ZF=1 → jnz atlamaz: sayı çift.
DX = cift_m; jmp yaz ile ortak yazdırma koduna gidilir.
“çift” iletisi yazılır.
CX = 3.
3 − 3 = 0 → ZF=1, CF=0. ZF=1 olduğu için ja atlamaz (3 ≤ 3).
'3' yazılır; 3 AND 1 = 1 → ZF=0 → tek.
“tek” iletisi yazılır.
CX = 4.
4 − 3 = 1 → ZF=0, CF=0 → ja bitti atlar (4 > 3).
ret: COM programı DOS'a döner. C'deki for + if, burada karşılaştırma + koşullu atlama çiftleriyle kuruldu.
org 100h
mov cx, 1 ; i = 1
dongu: cmp cx, 3 ; i ile n karşılaştır
ja bitti ; i > n ise bitir
mov dl, cl
add dl, '0' ; rakam → ASCII
mov ah, 02h
int 21h ; DL'yi yaz
test cl, 1 ; en düşük bit
jnz tek ; 1 ise tek
lea dx, cift_m
jmp yaz
tek: lea dx, tek_m
yaz: mov ah, 09h
int 21h ; dizgeyi yaz
inc cx ; i++
jmp dongu
bitti: ret
tek_m db ' sayisi bir tek sayidir.',0Dh,0Ah,'$'
cift_m db ' sayisi bir cift sayidir.',0Dh,0Ah,'$'Özet
Özet
- Yazılım donanımı yönetir; işletim sistemi temel yazılımdır, programlama dilleri yazılım geliştirmek için kullanılır.
- Makine dili işlemcinin tek anladığı dildir: işlem kodu ve işlenen alanlarından oluşan ikili komutlar; donanıma tamamen bağımlıdır.
- Çevirici dil makine komutlarını anımsatıcılarla yazar; çevirici ve bağlayıcı ile çalıştırılabilir dosyaya dönüşür. Kod hem işlemciye hem işletim sistemine bağlıdır (int 0x80, int 21h, DLL çağrısı, svc, sc).
- Derlenen diller (C, C++, Go, Rust, Fortran, Ada) önceden makine koduna çevrilir: hızlı, ama platforma özgü.
- Yorumlanan diller (Python, JavaScript, Ruby, PHP, Perl, MATLAB) çalışırken işlenir: hızlı geliştirme, taşınabilir kaynak, daha yavaş çalışma. Java/C# ara kod + JIT ile ikisinin arasındadır.
- Yüksek seviyedeki
for/if, assembly'de karşılaştırma + koşullu atlama olarak gerçeklenir.
Özet
Alıştırmalar
- Örnek makine dilinde
SUB R3, R0veOR R0, R2komutlarını ikili ve onaltılık olarak kodlayın. 0010 0111komutunu çözün. R1 = 9, R3 = 4 ise sonuç nedir?- Bu tasarımda kaç farklı işlem kodu tanımlanabilir? Yazmaç sayısını 8'e çıkarmak için komut biçimi nasıl değişmeli?
- DOS programında dizge sonundaki
'$'unutulursa ne olur? - Linux örneğinde
lenelle 15 yazılsaydı ekrana ne çıkardı? - Windows örneğinde parametreler neden ters sırada itilir?
call'dan hemen sonra ESP kaçtır? - Java neden “derlenen” ya da “yorumlanan” diye tek kelimeyle sınıflanamaz?
İpuçları / cevaplar
0010 1100= 2Ch;0100 0010= 42h.- SUB R1, R3 → R1 ← 9 − 4 = 5.
- 24 = 16. 8 yazmaç için 3'er bit gerekir: 4 + 3 + 3 = 10 bit (ya da işlem kodu 2 bite iner).
- DOS ilk '$' karakterine rastlayana kadar bellekteki rastgele baytları ekrana basar.
- “Merhaba, Linux!” yazılır ama satır sonu basılmaz (16. bayt).
- C çağrı kuralında ilk parametre yığının tepesinde olmalıdır; 4 push + dönüş adresi → ESP = 0012FF80h − 20 = 0012FF6Ch.
- Önce bytecode'a derlenir, sonra JVM'de yorumlanır/JIT ile derlenir: hibrittir.
Özet
Kaynaklar
- Tanenbaum ve Bos, Modern Operating Systems, 3. baskı, Pearson.
- Brey, The Intel Microprocessors, 8. baskı, Pearson.
- Irvine, Assembly Language for x86 Processors, 7. baskı, Pearson.
- NASM belgeleri (nasm.us) ve GNU Binutils as kılavuzu.
- Ralf Brown's Interrupt List (DOS INT 21h hizmetleri); Microsoft Win32 API belgeleri (
MessageBoxA,ExitProcess). - emu8086 belgeleri ve 8086 komut kümesi başvurusu.