Evo nekoliko osobina programskih jezika:
- Programski jezici su veštački jezici.
- Programski jezik služi za opis programa.
- Programski jezici su jednoznačni, ne dopuštaju dvosmislenost i neodređenost.
- Poželjne osobine programskih jezika su: jednostavnost, izražajnost, prenosivost-portabilnost, efikasnost …
Nema stroge (matematičke) definicije programskih jezika. Postoje razne opisne definicije.
- Programski jezik je veštački jezik koji služi za opis računarskih
- Programski jezik je skup sintaktičkih i semantičkih pravila korišćenih za opis (definiciju) računarskih programa.
- Programski jezik je veštački jezik za opis konstrukcija (pisanje instrukcija) koje mogu biti prevedene u mašinski jezik i izvršene na računaru.
Programski jezici su usko povezani sa programskim paradigmama.
Izdvojićemo posebno sledeće deficinije:
Programski jezik je veštački jezik koji nam omogućava zadavanje instrukcija računaru.
Instrukcija (niz naredbi) koju zadajemo računaru pomoću programskog jezika je računarski program.
Računarski program je opis algoritma-procesa u nekom programskom jeziku.
Kako računar računa
Računarski procesor je elektronski sklop koji je programabilan. U sebi sadrži elektronska kola/komponente za sve one operacije koje može da izvede (sabiranje, oduzimanje itd. – operacije niskog nivoa, koje se rade nad blokom bitova). Samo jedna od tih komponenti je aktivna u jednom trenutku, i kažemo da je to operacija koju procesor u tom trenutku radi. Sve komponente su povezane na jedan sklop (multiplekser) koji se ponaša kao skretnica – bira koja će komponenta biti uključena u nekom trenutku (sve ostale su isključene, kroz njih ne protiče struja, nisu u funkciji). Multiplekser uzima kod instrukcije – kombinaciju bitova – na osnovu kog bira jednu od komponenti koja će biti aktivna (u skladu sa kodom instrukcije).
Recimo da je kod instrukcije 8 bitova=1 bajt, procesor onda u sebi može da sadrži 28=256 različitih komponenti-operacija. (zapravo je kod instrukcije manji, procesor u sebi sadrži mali broj instrukcija) Ovakav procesor bi dakle učitavao bajt po bajt (instrukciju po instrukciju) i pobuđivao redom ovu ili onu komponentu-izvršavao ovu ili onu instrukciju. To je način na koji je izvedena programabilnost procesora i način na koji se formira program.
Procesor će dobrim delom da čita i piše u memoriju, tj. da menja stanje sistema. Ako želimo da u memoriji predstavimo nekakvo stanje, to postižemo time što napravimo niz instrukcija koje će procesor da izvrši kako bi u memoriju upisao one podatke koje želimo, a koji opisuju to stanje. Dakle, nizom instrukcija programiramo mašinu da sebe (svoju memoriju) dovede u takvo stanje koje oslikava naš model te neke stvarne ili fiktivne realnosti.
Na ovom nivou izražavanja jedino što možemo da izrazimo su prosti imperativni iskazi: upiši u memorijsku adresu nešto, pročitaj iz memorijske adrese, ako je u registru nekakva vrednost preskoči sledeću instrukciju... Otud se ovakav pristup pisanju programa zove imperativni.
Von Neumann-ov koncept računara
(Videti naučni rad: Burks, Goldstine and von Neumann , 1947. https://www.cs.princeton.edu/courses/archive/fall10/cos375/Burks.pdf)

Slika 1. Von Nojmanov koncept računara
Von Nojmanov koncept računara leži u osnovi konstrukcije elektronskih računara. Ideja je sledeća: postoji skladište-memorija u kojem se nalaze i podaci i instrukcije. Procesor kreće izvršavanje od početka memorije, tako što učitava instrukciju iz prvog bajta. Zavisno od sadržaja tog bajta (binarni oblik) aktiviraće se odgovarajući deo procesora i izvršiće se takva instrukcija. Interni brojač instrukcija se inkrementira (+1) i procesor učitava sledeću instrukciju, i tako redom do kraja. Instrukcije mogu da budu i za skok (jump) tako da program ne mora da bude nužno linearni niz instrukcija kroz koje se prođe jednom i to je to, već omogućava i skakanje kroz program – i unapred i unazad. Time se omogućava grananje, št je preduslov za uslove (if-else) i petlje (while,for).
Neka svojstva Von Nojmanovog tipa računara su:
- memorija je odvojena od aritmetičko-logičke jedinice
- u istoj memoriji se čuvaju i podaci i instrukcije
- instrukcije i podaci su u binarnom obliku, tipično organizovani u bajtove
- instrukcije i podaci se prenose iz memorije u procesor i obrnuto preko magistrale – ožičene veze, kabla
- niz instrukcija – program – opisuje radnju koju računar treba da izvrši
- računar podatke iz memorije učitava/kopira u svoje interne registre (memorijske jedinice)
- računar podatke u memoriju upisuje iz svojih internih registara (kopira)
- instrukcije se izvršavaju jedna za drugom dok se ne izvrši eksplicitni skok naredbom JUMP/GOTO
Uticaj Von Nojmanovog tipa računara na dizajniranje mašinskih programskih jezika
Navedena svojstva uticala su da osnovni pojam jezika bude naredba, pa se otud nazivaju imperativni programski jezici. Naredbe se grupišu u procedure (imenovani blok naredbi koji može da se pozove na više mesta u programu, da se kod ne bi duplirao). Naredbe se izvršavaju sekvencijalno, jedna po jedna, redom, osim ako se ne dođe do naredbe koja izaziva skok na neku drugu naredbu (unazad ili unapred, JUMP/GOTO). Iteracija (ponavljanje, petlja) je efikasan metod i predstavlja praktično glavni metod u rešavanju problema.
Procedurom se računaru saopštava kako se rešava problem. Opisuje se postupak, korak po korak.
Oznake promenljivih su zapravo oznake memorijskih lokacija u kojima se nalaze podaci. Promenljiva služi programeru da lakše razume i piše program. Očigledno je lakše napisati X=2; nego 0x16F04=2. Dakle, uvodi se neki oblik apstrakcije računarskog uređaja. Ovo može dovesti do problema jer se u naredbama oznake promenljivih koriste i kao adresa i kao vrednost na toj adresi, zavisno od naredbe. Ovo čini nezgrapnim one jezike koji omogućavaju direktno baratanje sa pokazivačima, i moderniji jezici to uglavnom teže da uklone.
Elektronski računari mogu da izvršavaju jedino programe izražene na mašinskom jeziku, sačinjene od instrukcija koje procesor prepoznaje. Izvršni program mora da bude zapisan u binarnom formatu. Ako je program pisan na nekom drugom jeziku vrši se prevođenje na mašinski jezik. Prevođenje vrši namenski program-prevodilac.
Prevođenje sa mašinski-orijentisanih jezika na mašinski jezik obavljaju asembleri.
Prevođenje sa viših programskih jezika na mašinski jezik, obavljaju kompilatori i interpretatori.
Kompilatori-kompajleri generišu izvršni fajl koji može da se pokrene (.exe) a interpretatori tumače kod u hodu i izvršavaju ga.
Analiza – razlaganje programa do mašinskih instrukcija
Fon Nojmanova arhitektura računara kao najpopularniji oblik računarskih uređaja odredila je dizajn ranih programskih jezika. Procesor kao programabilni uređaj radi tako što izvršava niz naredbi, koje se nalaze u memoriji u uzastopnim memorijskim jedinicama (susednim adresama, redom), pri čemu je svaka naredba binarni podatak koji sadrži OPCOD – određen broj bitova čija kombinacija određuje koji deo procesora će biti aktivan, odnosno bira instrukciju koju će procesor da izvrši onda kada dođe do te naredbe i učita je iz memorije. Naredbe mogu biti i uslovni skok, čime se izaziva da procesor preskoči na neku naredbu negde u programu (da se vrati unazad ili preskoči napred) čime dobijamo mogućnosti izražavanja uslova, grananja (ako X onda radi ovo, inače radi ono), i cikličnog ponavljanja bloka instrukcija (petlje), kao i neke zgodne optimizacije: procedure i funkcije – blokovi instrukcija na koje će se u programu skakati više puta, a koji će po završetku izazvati skok nazad na mesto odakle se skočilo na početak bloka procedure/funkcije – return.
Ovakav pristup programiranju računara doveo je do nastanka programskih jezika koji su samo nešto viša apstrakcija mašinskog koda – umesto da pišemo svaku pojedinačnu instrukciju iz seta instrukcija procesora (instrukcije niskog nivoa-sabiranje, shift, poređenje, uslovni skok i dr.) i vodimo računa o memorijskim adresama i gde se šta nalazi u memoriji, programski jezici nam omogućavaju da kroz neke konstrukcije višeg nivoa apstrakcije izrazimo postupak/algoritam, koji će se zatim namenskim programom-prevodiocem (kompajler) prevesti u mašinski kod koji procesor može da izvrši.
Sledeći kod:
sum = 0;
for(i=0; i<10; i++){
sum += i;
}
se podjednako može zapisati i jednostavnim instrukcijama kao:
sum = 0;
i = 0;
while(i<10){
sum = sum + i;
i = i + 1;
}
i dalje još primitivnijim setom instrukcija kao:
- sum=0
- i=0
- loop:
- sum = sum+i
- i = i+1
- if i<10 goto loop
- end;
gde su brojevi na početku svakog reda redni broj svake instrukcije,koji se može preslikati na odgovarajuću adresu u memoriji. Ako bismo išli još dalje mogli bismo da napišemo i ovako nešto...
Uzećemo da adresiranje kreće od 0, da se adrese zapisuju u obliku 0x0000 – četvorocifreni heksadekadni broj (2 bajta/16 bita), a da procesor ima registre A,B,C,D i instrukcije
- MOV1 adresa,registar – učitaj iz memorije u registar
- MOV2 registar,adresa– upiši iz registra u memoriju
- MOV3 registar, broj – upiši zadati broj u registar
- ADD registar,registar– saberi dva registra, rezultat upiši u prvi
- ADD registar, broj – saberi broj na registar, rezultat upiši u registar
- CMP registar, registar – uporedi dva registra i u statusni registar upiši -1,0,1 ako je prvi manji,jednak ili veći od drugog
- JMP adresa – skoči na adresu
- JMPIFM adresa – skoči na adresu ako je u statusnom registru upisano -1
- JMPIFJ adresa – skoči na adresu ako je u statusnom registru upisano 0
- JMPIFV adresa – skoči na adresu ako je u statusnom registru upisano 1
Ovo što smo napisali zapravo nije daleko od stvarnog asemblera za Intel8086.
Program bi izgledao ovako:
|
Adresa |
Instrukcija / podatak |
Komentar |
|
0x0000 |
MOV A, 0 |
sum=0 |
|
0x0001 |
MOV B, 0 |
i=0 |
|
0x0002 |
ADD A, B |
sum = sum + i, pocetak petlje |
|
0x0003 |
ADD B, 1 |
i = i + 1 |
|
0x0004 |
MOV C, 10 |
|
|
0x0005 |
CMP B, C |
if i < 10 |
|
0x0006 |
JMPIFM 0x0002 |
goto loop |
|
0x0007 |
MOV A, 0x000A |
upisi sum u memoriju |
|
0x0008 |
MOV B, 0x000B |
upisi i u memoriju |
|
0x0009 |
END |
kraj programa |
|
0x000A |
0 |
sum, inicijalna vrednost |
|
0x000B |
0 |
i, inicijalna vrednost |
Zamislite umesto MOV, ADD, CMP... binarne vrednosti koje su kombinacije tih instrukcija i eto vam mašinskog koda koji procesor izvršava.