Bölüm 3: Programlama Dilleri
Giriş
Öğrenme Çıktıları
Makine dili, assembly dili ve yüksek seviyeli diller arasındaki farkı açıklamak.
Bir komut biçimine göre ikili komutları kodlamak ve çözmek.
Assembler ve bağlayıcının kaynak kodu nasıl çalıştırılabilir dosyaya çevirdiğini açıklamak; 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.
- Assembly dilleri: 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.Yazılım · Kodu adım adım çalıştır
Kod İzleme: x = a + b Bellekte Nasıl Çalışır?
org 100h mov ax, [0200h] ; A1 00 02 add ax, [0202h] ; 03 06 02 02 mov [0204h], ax ; A3 04 02 ret ; C3
IP = 0100h. Getir: A1 00 02 okunur. A1 = “AX'e bellekten sözcük yükle”, adres baytları 00 02 → 0200h (little-endian).
Yürüt: 0200h ve 0201h'deki baytlar 15 00 → AX = 0015h (a = 21). IP = 0103h.
Getir: 03 06 02 02 (4 bayt). 03 = ADD r16, r/m16; ModR/M 06 = “AX, doğrudan adres”; adres 0202h.
Yürüt: b = 0027h (39) okunur, AX = 15h + 27h = 003Ch (60). IP = 0107h.
Getir: A3 04 02: A3 = “AX'i belleğe yaz”, hedef adres 0204h.
Yürüt: AX belleğe düşük bayt önce yazılır: 0204h ← 3C, 0205h ← 00. x = 60.
C3 = RET. C'deki tek satır x = a + b; burada 3 komut, 10 bayt makine kodu oldu.
Varsayım: a = 0015h (21), b = 0027h (39); veri kesimi kodla aynı (COM programı).
Makine Dili
Makine Dilleri
- 0 ve 1'lerden oluşan en düşük 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.
- Assembly dilleri 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
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.
Assembly Dilleri
Assembly Dilleri
- 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ı assembly dilleri vardır.
- Mikrodenetleyicilere özel assembly dilleri 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 assembler denir.
Assembly Dilleri
Kaynak Koddan Çalışan Programa
Assembler'ın 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.
Assembly Dilleri · Kodu adım adım çalıştır
Kod İzleme: Assembler'ın İki Geçişi
org 100h mov ah, 09h mov dx, offset mesaj int 21h mov ax, 4C00h int 21h mesaj db 'Merhaba!$'
1. geçiş yalnız adres sayar. org 100h konum sayacını (LC) 0100h yapar; direktif bayt üretmez.
mov ah, 09h 2 bayt tutar → LC = 0102h. Baytların kendisi henüz yazılmaz.
offset mesaj ileri başvurudur: mesaj henüz tanımlanmadı ama komutun 3 bayt olduğu bilinir → LC = 0105h.
int 21h (2), mov ax, 4C00h (3), int 21h (2): LC = 010Ch.
Etiket mesaj şu anki LC ile sembol tablosuna girer: mesaj = 010Ch. 9 baytlık dizgi → LC = 0115h.
2. geçiş baştan başlar ve baytları üretir: mov ah, 09h → B4 09.
offset mesaj artık tablodan bulunur: 010Ch → BA 0C 01 (adres little-endian).
Kalan komutlar: CD 21, B8 00 4C, CD 21.
Dizginin ASCII kodları yazılır: 4D 65 72 … 24 ('$'). Çıktı 21 baytlık COM dosyası; çalıştırılınca ekrana Merhaba! yazar.
Assembly Dilleri
Assembler'lar ve Söz Dizimleri
| Assembler | Söz dizimi · 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.
Assembly Dilleri · Kodu adım adım çalıştır
x86 Assembly: Linux (32 bit, NASM)
Veri bölümü: dizgi 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 = dizginin 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
“Merhaba, Dünya!” metninde ü harfi UTF-8'de 2 bayt olduğundan metin 16 bayttır; equ $ - hello uzunluğu assembler'a hesaplatır.
Assembly Dilleri
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 … |
Assembly Dilleri · 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 dizgiyi yaz” hizmeti.
lea dx, mesaj: DS:DX dizginin 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!$'
09h hizmeti '$' sonlandırıcı bekler; veri kodun arkasına konur, önde olsaydı komut gibi çalıştırılırdı. mov ax, 4C00h AL'yi (çıkış kodu) de sıfırlar.
Assembly Dilleri
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.
- Dizgiler 0 ile biter (C dizgisi).
- Bağlarken süslenmiş ad gerekebilir:
_MessageBoxA@16(16 = parametre baytı).
Assembly Dilleri · 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 dizgisinin adresi itilir.
push mesaj: metin dizgisinin 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
Assembly Dilleri
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.
Assembly Dilleri
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.
GNU as'ta db değil .ascii kullanılır; . - mesaj uzunluğu assembler'a hesaplatır.
Assembly Dilleri
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).
Assembly Dilleri
Aynı “Merhaba”, Altı Ortam
| Ortam | İşlemci | OS'a geçiş | Hizmet no. | Parametreler | Dizgi 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 |
;, ARM GNU'da @, PowerPC'de #. Yüksek seviyeli dillerin en büyük kazancı bu bağımlılığı derleyiciye/yorumlayıcıya devretmektir.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 · Kodu adım adım çalıştır
Kod İzleme: Derleyicinin Ürettiği Döngü
org 100h mov bx, 0 ; toplam = 0 mov cx, 10 ; i = 10 kosul: cmp cx, 0 ; i > 0 ? jle bitti add bx, cx ; toplam += i sub cx, 3 ; i -= 3 jmp kosul bitti: mov toplam, bx ret toplam dw ?
Derleyici değişkenleri yazmaçlara yerleştirdi: toplam → BX, i → CX. while koşulu döngünün başında sınanır.
cmp cx, 0 + jle: i = 10 > 0 olduğundan atlanmaz, gövdeye girilir (C'deki koşul tersine çevrilip “çık” atlamasına dönüştü).
Gövde: toplam = 10, i = 7; jmp kosul ile koşula dönülür.
cmp cx, 0 + jle: i = 7 > 0 olduğundan atlanmaz, gövdeye girilir (C'deki koşul tersine çevrilip “çık” atlamasına dönüştü).
Gövde: toplam = 17, i = 4; jmp kosul ile koşula dönülür.
cmp cx, 0 + jle: i = 4 > 0 olduğundan atlanmaz, gövdeye girilir (C'deki koşul tersine çevrilip “çık” atlamasına dönüştü).
Gövde: toplam = 21, i = 1; jmp kosul ile koşula dönülür.
cmp cx, 0 + jle: i = 1 > 0 olduğundan atlanmaz, gövdeye girilir (C'deki koşul tersine çevrilip “çık” atlamasına dönüştü).
Gövde: toplam = 22, i = -2; jmp kosul ile koşula dönülür.
i = -2: koşul i > 0 yanlış (i ≤ 0, SF ≠ OF) → jle bitti atlar, döngüden çıkılır.
Sonuç belleğe yazılır: toplam = 22. Tek bir C döngüsü; karşılaştırma, koşullu atlama ve koşulsuz atlamaya çevrildi.
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öz dizimi 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 - Tamsayı
Get/PutiçinAda.Integer_Text_IOgerekir;Put_Linesatır sonu ekler.
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.===: 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) |
Yüksek Seviyeli Diller · Kodu adım adım çalıştır
Kod İzleme: Ara Kod (Bytecode) Nasıl Çalışır?
// x = (a + b) * c; iload a // a'yı yığına it iload b // b'yi yığına it iadd // üst iki öğeyi topla iload c imul // üst iki öğeyi çarp istore x // yığından x'e yaz return
Derleyici x = (a + b) * c için yığın tabanlı ara kod (bytecode) üretti. Yerel değişkenler: a = 6, b = 7, c = 3. iload a: yerel değişken a = 6 yığının üstüne itilir.
iload b: yerel değişken b = 7 yığının üstüne itilir.
iadd: üstteki iki öğe (6, 7) çekilir, toplam 13 itilir. İşlenen adı yok; hepsi yığında.
iload c: yerel değişken c = 3 yığının üstüne itilir.
imul: 13 × 3 = 39 yığına itilir.
istore x: yığının üstü x'e yazılır → x = 39; yığın boşaldı.
Bu ara kod hiçbir işlemciye bağlı değil: sanal makine (JVM, CLR) her komutu ya yorumlar ya da JIT ile 8086/x86 gibi gerçek makine koduna çevirir.
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 olarak koda yazıldı; klavyeden okunmuyor.
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 dizgisinin 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.
- Assembly dili makine komutlarını anımsatıcılarla yazar; assembler 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 dizgi 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.