Çekirdek örnekleri: KabaLang Minimal Kernel (MPL-2.0) ve üç küçük çekirdek

KabaLang'ın --yalin kipiyle yazılmış, işletim sistemi olmadan açılan
x86-64 çekirdeği: kesmeler, 100 Hz zamanlayıcı, Türkçe Q klavye,
Türkçe karakterli VGA ekranı, bellek haritası, sayfa ayırıcı, kabuk.
Ek örnekler: merhaba, asal sayılar, VGA renkleri.
This commit is contained in:
2026-10-17 13:09:50 +03:00
parent e0e4a0d6c7
commit c5468f5d0a
24 changed files with 2279 additions and 2 deletions
+149
View File
@@ -0,0 +1,149 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/* KabaLang yalın (çıplak donanım) çekirdek önyükleme parçası.
*
* Görevi YALNIZ: Multiboot1 başlığı (QEMU `-kernel` ve GRUB yükler),
* 32 bit korumalı kipten 64 bit uzun kipe geçiş, yığın, ve KabaLang
* programının giriş işlevine (`kaba_cekirdek_ana`) atlamak. Çekirdeğin
* MANTIĞI bu dosyada değil, `.kbl` kaynağındadır.
*
* Bellek: ilk 1 GB, 2 MB'lık sayfalarla birebir (identity) eşlenir.
*/
.set MB_SIHIR, 0x1BADB002
.set MB_BAYRAK, 0x00000003 /* sayfa hizalı modüller + bellek bilgisi */
.set MB_SAGLAMA, -(MB_SIHIR + MB_BAYRAK)
.section .multiboot, "a"
.align 4
.long MB_SIHIR, MB_BAYRAK, MB_SAGLAMA
.section .bss
.align 4096
.global kaba_yigin_durumu
kaba_yigin_durumu: /* yalın çalışma zamanının yığın durumu */
.skip 64
.align 4096
pml4: .skip 4096
pdpt: .skip 4096
pd: .skip 4096
yigin_alt:
.skip 65536
yigin_ust:
.section .data
.align 8
.global kaba_onyukleme_bilgisi
kaba_onyukleme_bilgisi:
.quad 0
.section .rodata
.align 8
gdt64:
.quad 0 /* boş tanımlayıcı */
.quad 0x00AF9A000000FFFF /* 64 bit kod kesimi */
.quad 0x00CF92000000FFFF /* veri kesimi */
gdt64_son:
gdt64_gosterge:
.word gdt64_son - gdt64 - 1
.quad gdt64
.section .text
.code32
.global _start
_start:
cli
mov $yigin_ust, %esp
mov %ebx, kaba_onyukleme_bilgisi /* Multiboot bilgi yapısının adresi */
/* PML4[0] → PDPT, PDPT[0] → PD, PD[i] → i*2MB (büyük sayfa) */
mov $pdpt, %eax
or $0x3, %eax
mov %eax, pml4
mov $pd, %eax
or $0x3, %eax
mov %eax, pdpt
xor %ecx, %ecx
1: mov %ecx, %eax
shl $21, %eax
or $0x83, %eax /* var + yazılabilir + büyük sayfa */
mov %eax, pd(,%ecx,8)
inc %ecx
cmp $512, %ecx
jne 1b
mov $pml4, %eax /* CR3 = PML4 */
mov %eax, %cr3
mov %cr4, %eax /* PAE */
or $0x20, %eax
mov %eax, %cr4
mov $0xC0000080, %ecx /* EFER.LME */
rdmsr
or $0x100, %eax
wrmsr
mov %cr0, %eax /* sayfalama + korumalı kip */
or $0x80000001, %eax
mov %eax, %cr0
lgdt gdt64_gosterge
ljmp $0x08, $uzun_kip
.code64
uzun_kip:
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %ss
xor %ax, %ax
mov %ax, %fs
mov %ax, %gs
mov $yigin_ust, %rsp
xor %rbp, %rbp
call kaba_cekirdek_ana
2: cli
hlt
jmp 2b
/* ── Kesme girişleri ────────────────────────────────────────────────────
* 0–31 işlemci istisnaları, 32–47 PIC donanım kesmeleri (yeniden eşlenmiş).
* Her giriş: (hata kodu yoksa 0) + vektör yığına → ortak giriş → KabaLang
* `kesme(vektor, kod)` (dışa `kaba_kesme`). Yazmaçlar saklanır; yığın
* `call` anında 16 bayt hizalıdır (5 CPU + 2 giriş + 15 yazmaç = 22×8 = 176).
* Çekirdek `-mgeneral-regs-only` derlendiği için SSE durumu saklanmaz. */
/* CPU'nun hata kodu ittiği istisnalar: 8, 10–14, 17, 21, 29, 30. */
.irp n, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47
kesme_giris_\n:
.if (\n == 8) || (\n >= 10 && \n <= 14) || (\n == 17) || (\n == 21) || (\n == 29) || (\n == 30)
.else
push $0
.endif
push $\n
jmp kesme_ortak
.endr
kesme_ortak:
.irp r, rax,rbx,rcx,rdx,rsi,rdi,rbp,r8,r9,r10,r11,r12,r13,r14,r15
push %\r
.endr
mov 120(%rsp), %rdi /* vektör */
mov 128(%rsp), %rsi /* hata kodu */
cld
call kaba_kesme
.irp r, r15,r14,r13,r12,r11,r10,r9,r8,rbp,rdi,rsi,rdx,rcx,rbx,rax
pop %\r
.endr
add $16, %rsp /* vektör + hata kodu */
iretq
/* Program `kesme` işlevi tanımlamadıysa: hiçbir şey yapma. */
.weak kaba_kesme
kaba_kesme:
ret
.section .rodata
.align 8
.global kaba_kesme_girisleri
kaba_kesme_girisleri:
.irp n, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47
.quad kesme_giris_\n
.endr
@@ -0,0 +1,318 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
#
# KabaLang yalın çalışma zamanı — KabaLang ile yazılmıştır.
#
# Yalın (çıplak donanım) derlemelere kendiliğinden eklenir. Buradaki
# `kaba_*` adlı işlevler, normal LLVM yolunda C++ çalışma zamanının verdiği
# C ABI işlevlerinin karşılığıdır; üreteç onları aynı adla dışa açar
# (işaretçiler burada 64 bit sayı olarak görünür). Böylece metin işlemleri
# (birleştirme, karşılaştırma, uzunluk, parça…) çekirdekte de normal
# KabaLang yazımıyla kullanılabilir.
#
# Yığın: `yigin_kur(adres, boyut)` ile çekirdeğin verdiği bölge. İlk uyan
# boş blok kullanılır, büyük blok bölünür; boş blok yoksa bölgenin
# sonundan ilerlenir. Bellek biterse işlemci durdurulur.
#
# Metin düzeni: [sayaç: 8][uzunluk (bayt): 8][baytlar][0]
# sayaç < 0 → ölümsüz (derleme zamanında gömülen sabit metin).
# Uzunluk ve indeks KOD NOKTASI üzerinden çalışır (UTF-8).
BASLIK = 16 # blok başlığı: [boyut][sonraki]
METIN_BASLIK = 16 # metin başlığı: [sayaç][uzunluk]
# Yığın durumu `yigin_durumu()` adresindedir (önyükleme parçasında 64 bayt).
BOS_LISTE = 0
KULLANILAN = 8
SINIR = 16
SON = 24
# ── yığın ────────────────────────────────────────────────────────────────
fonksiyon yigin_kur(adres, boyut):
d = yigin_durumu()
bellek_yaz64(d + BOS_LISTE, 0)
bellek_yaz64(d + KULLANILAN, 0)
bellek_yaz64(d + SINIR, adres)
bellek_yaz64(d + SON, adres + boyut)
fonksiyon yigin_kullanilan():
don bellek_oku64(yigin_durumu() + KULLANILAN)
fonksiyon kaba_ayir(n):
d = yigin_durumu()
boyut = bit_ve(n + 15, bit_degil(15)) + BASLIK
onceki = 0
blok = bellek_oku64(d + BOS_LISTE)
iken blok != 0:
bb = bellek_oku64(blok)
eger bb >= boyut:
eger bb - boyut >= 64:
# Bloğun SONUNDAN kes; kalan parça listede kalır.
bellek_yaz64(blok, bb - boyut)
yeni = blok + bb - boyut
bellek_yaz64(yeni, boyut)
bellek_yaz64(d + KULLANILAN, bellek_oku64(d + KULLANILAN) + boyut)
don yeni + BASLIK
sonraki = bellek_oku64(blok + 8)
eger onceki == 0:
bellek_yaz64(d + BOS_LISTE, sonraki)
degilse:
bellek_yaz64(onceki + 8, sonraki)
bellek_yaz64(d + KULLANILAN, bellek_oku64(d + KULLANILAN) + bb)
don blok + BASLIK
onceki = blok
blok = bellek_oku64(blok + 8)
sinir = bellek_oku64(d + SINIR)
eger sinir == 0 veya sinir + boyut > bellek_oku64(d + SON):
dur()
bellek_yaz64(d + SINIR, sinir + boyut)
bellek_yaz64(sinir, boyut)
bellek_yaz64(d + KULLANILAN, bellek_oku64(d + KULLANILAN) + boyut)
don sinir + BASLIK
fonksiyon kaba_serbest(p):
eger p == 0:
don 0
d = yigin_durumu()
blok = p - BASLIK
bellek_yaz64(d + KULLANILAN, bellek_oku64(d + KULLANILAN) - bellek_oku64(blok))
bellek_yaz64(blok + 8, bellek_oku64(d + BOS_LISTE))
bellek_yaz64(d + BOS_LISTE, blok)
don 0
# ── metin yardımcıları ───────────────────────────────────────────────────
fonksiyon bayt_uzunluk(m):
don bellek_oku64(m + 8)
fonksiyon veri(m):
don m + METIN_BASLIK
fonksiyon yeni_metin(n):
m = kaba_ayir(METIN_BASLIK + n + 1)
bellek_yaz64(m, 1)
bellek_yaz64(m + 8, n)
bellek_yaz8(m + METIN_BASLIK + n, 0)
don m
fonksiyon kopyala(hedef, kaynak, n):
dongu i icinde 0..n - 1:
bellek_yaz8(hedef + i, bellek_oku8(kaynak + i))
fonksiyon devam_bayti_mi(b):
don bit_ve(b, 0xC0) == 0x80
fonksiyon kod_noktasi_ofseti(m, k):
# k. kod noktasının bayt ofseti; k uzunluğa eşitse bayt uzunluğu.
n = bayt_uzunluk(m)
i = 0
sayac = 0
iken i < n:
eger degil devam_bayti_mi(bellek_oku8(veri(m) + i)):
eger sayac == k:
don i
sayac = sayac + 1
i = i + 1
don n
fonksiyon alt_metin(m, bas, son):
# [bas, son) bayt aralığından yeni metin.
r = yeni_metin(son - bas)
kopyala(veri(r), veri(m) + bas, son - bas)
don r
# ── C ABI karşılıkları (normal yolda kaba_rt.cpp) ────────────────────────
fonksiyon kaba_m_tut(m):
eger m != 0 ve bellek_oku64(m) >= 0:
bellek_yaz64(m, bellek_oku64(m) + 1)
fonksiyon kaba_m_birak(m):
eger m == 0:
don 0
s = bellek_oku64(m)
eger s > 0:
eger s == 1:
kaba_serbest(m)
degilse:
bellek_yaz64(m, s - 1)
don 0
fonksiyon kaba_m_sabit(p, n):
r = yeni_metin(n)
kopyala(veri(r), p, n)
don r
fonksiyon kaba_m_cden(p):
n = 0
iken bellek_oku8(p + n) != 0:
n = n + 1
don kaba_m_sabit(p, n)
fonksiyon kaba_m_birlestir(a, b):
la = bayt_uzunluk(a)
lb = bayt_uzunluk(b)
r = yeni_metin(la + lb)
kopyala(veri(r), veri(a), la)
kopyala(veri(r) + la, veri(b), lb)
don r
fonksiyon kaba_m_birlestir_tasi(a, b):
# Sol taraf geçicidir: sonuç üretilir, sol bırakılır.
r = kaba_m_birlestir(a, b)
kaba_m_birak(a)
don r
fonksiyon kaba_m_karsilastir(a, b):
la = bayt_uzunluk(a)
lb = bayt_uzunluk(b)
n = la
eger lb < n:
n = lb
dongu i icinde 0..n - 1:
x = bellek_oku8(veri(a) + i)
y = bellek_oku8(veri(b) + i)
eger x < y:
don 0 - 1
eger x > y:
don 1
eger la < lb:
don 0 - 1
eger la > lb:
don 1
don 0
fonksiyon kaba_m_esit(a, b):
eger bayt_uzunluk(a) != bayt_uzunluk(b):
don 0
eger kaba_m_karsilastir(a, b) == 0:
don 1
don 0
fonksiyon kaba_m_uzunluk(m):
n = bayt_uzunluk(m)
sayac = 0
dongu i icinde 0..n - 1:
eger degil devam_bayti_mi(bellek_oku8(veri(m) + i)):
sayac = sayac + 1
don sayac
fonksiyon kaba_m_bos_mu(m):
eger bayt_uzunluk(m) == 0:
don 1
don 0
fonksiyon kaba_m_sayidan(n):
eksi = n < 0
eger eksi:
n = 0 - n
basamak = 1
b = n
iken b >= 10:
b = b // 10
basamak = basamak + 1
uzun = basamak
eger eksi:
uzun = uzun + 1
r = yeni_metin(uzun)
eger eksi:
bellek_yaz8(veri(r), 0x2D)
k = uzun - 1
dongu j icinde 1..basamak:
bellek_yaz8(veri(r) + k, 0x30 + n % 10)
n = n // 10
k = k - 1
don r
fonksiyon kaba_m_sayiya(m):
n = bayt_uzunluk(m)
i = 0
eksi = yanlis
eger n > 0 ve bellek_oku8(veri(m)) == 0x2D:
eksi = dogru
i = 1
sonuc = 0
iken i < n:
c = bellek_oku8(veri(m) + i)
eger c < 0x30 veya c > 0x39:
don 0
sonuc = sonuc * 10 + (c - 0x30)
i = i + 1
eger eksi:
don 0 - sonuc
don sonuc
fonksiyon kaba_m_mantiktan(b):
eger b != 0:
don kaba_m_cden(veri_adresi("doğru"))
don kaba_m_cden(veri_adresi("yanlış"))
fonksiyon kaba_m_oge(m, i, satir):
n = kaba_m_uzunluk(m)
eger i < 0:
i = i + n
eger i < 0 veya i >= n:
dur()
don alt_metin(m, kod_noktasi_ofseti(m, i), kod_noktasi_ofseti(m, i + 1))
fonksiyon kaba_m_parca(m, bas, uzunluk):
n = kaba_m_uzunluk(m)
eger bas < 0:
bas = 0
eger bas > n:
bas = n
son = n
eger uzunluk >= 0 ve bas + uzunluk < n:
son = bas + uzunluk
don alt_metin(m, kod_noktasi_ofseti(m, bas), kod_noktasi_ofseti(m, son))
fonksiyon kaba_m_ile_baslar(m, onek):
lo = bayt_uzunluk(onek)
eger lo > bayt_uzunluk(m):
don 0
dongu i icinde 0..lo - 1:
eger bellek_oku8(veri(m) + i) != bellek_oku8(veri(onek) + i):
don 0
don 1
fonksiyon bayt_bul(m, parca):
lm = bayt_uzunluk(m)
lp = bayt_uzunluk(parca)
eger lp == 0:
don 0
i = 0
iken i + lp <= lm:
tutar = dogru
j = 0
iken tutar ve j < lp:
eger bellek_oku8(veri(m) + i + j) != bellek_oku8(veri(parca) + j):
tutar = yanlis
j = j + 1
eger tutar:
don i
i = i + 1
don 0 - 1
fonksiyon kaba_m_icerir(m, parca):
eger bayt_bul(m, parca) >= 0:
don 1
don 0
fonksiyon kaba_m_bul(m, parca):
b = bayt_bul(m, parca)
eger b < 0:
don 0 - 1
# bayt ofsetinden kod noktası dizinine
sayac = 0
dongu i icinde 0..b - 1:
eger degil devam_bayti_mi(bellek_oku8(veri(m) + i)):
sayac = sayac + 1
don sayac
fonksiyon kaba_m_tekrarla(m, n):
l = bayt_uzunluk(m)
eger n < 0:
n = 0
r = yeni_metin(l * n)
dongu k icinde 0..n - 1:
kopyala(veri(r) + k * l, veri(m), l)
don r
@@ -0,0 +1,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/* KabaLang yalın çekirdek bağlayıcı betiği — 1 MB'tan başlar (Multiboot1). */
ENTRY(_start)
SECTIONS
{
. = 1M;
.text : ALIGN(4K) {
KEEP(*(.multiboot))
*(.text .text.*)
}
.rodata : ALIGN(4K) { *(.rodata .rodata.*) }
.data : ALIGN(4K) { *(.data .data.*) }
.bss : ALIGN(4K) { *(COMMON) *(.bss .bss.*) }
/DISCARD/ : { *(.comment) *(.note*) *(.eh_frame*) }
}