9
3. Razvojno okruženje Razvojna sredstva savremenih računara opšte namene kakve su PC mašine (desktops) koriste veoma složene tehnike za prevođenje programa kreiranih na nekim od HLL-ova. Pri tome u najvećem broju slučajeva izvorni kôd se direktno prevodi u binarni image-oblik koji se zatim load-uje u mašinu radi izvršenja. U suštini, ova sofisticirana razvojna sredstva prevode izvorni kôd u relokatibilne module, ponekad koristeći, a često i nekoristeći debug i simboličke informacije koje mogu biti od koristi projektantima. Pri tome, složeni i dobro optimizirani linker-i i loader-i dinamički kombinuju ove module, i u trenutku izvršenja aplikacije preslikavaju ove module u specifične memorijske lokacije. Sa druge strane, projektanti embedded sistema ne mogu da koriste ovakve beneficije iz nekoliko razloga. Kao prvo, embedded sistem se skoro uvek bazira na jedinstvenom (specifičnom) hardveru, hardver koji u suštini ne postoji (ne egzistira kao takav) kada se razvijalo razvojno sredstvo. Kao drugo, uprkos prednosti kojom se karakteriše procesor ugrađen u razvojno sredstvo, ipak postoji neznatna razlika u mašinskim jezicima između izabranog procesora i procesora ugrađenog u razvojnom okruženju, nezavisno od toga što oba procesora pripadaju istoj familiji (procesori Intel 286, 186, 288, 188, i td.). Pored toga, deo napora koje učini projektant moraju biti usmereni ka tome da se naredi razvojnom sredstvu na koji način da prevede izvorni kôd za specifični hardver embedded sistema. To znači da projektanti embeded sistema moraju da znaju mnogo više detalja o tome: a) na koji način njihova razvojna sredstva rade; b) kako izgleda razvojno okruženje; c) na koji način se izvršavaju programi. 3.1 Radno okruženje Pored dobrog poznavanja ISA (Instruction Set Architecture) tj. procesora, da bi se kreirao efikasan embedded kôd, projektantu je dodatno potrebno da dobro poznaje i sledeće detalje: 1) na koji način sistem koristi memoriju, uključujući i detalje koji se odnose na to na koji način procesor manipuliše magacinom, 2) šta se dešava pri startup sistema, i 3) na koji način se manipuliše sa prekidima i izuzecima? Da bi ukazali, sa nešto više detalja, na ove probleme analilzira ćemo rad jednog tipičnog embedded sistema zasnovanog na procesorima iz familije Motorola 68000 (68K). 3.2. Organizacija memorije Prvu stvar sa kojom se projektant embedded sistema suočava, a tiče se rada sistema, predstavlja način na koji on vidi memoriju, i kako se koristi ta memorija. Ilustracije radi, na slici 3.1 prikazan je memorijski model procesora Motorola 68K kao jednog tipičnog reprezenta procesora koji se ugrađuju u embedded sisteme. Kao što se vidi sa slike 3.1 sve što je na levoj strani u odnosu na U/I prostor može se implementirati kao ROM, a sve što je na desnoj kao RAM. Slika 3.1. Memorijska mapa procesorskog sistema

3. Razvojno okruženje - es.elfak.ni.ac.rses.elfak.ni.ac.rs/es/Materijal/Pog.3-Razvojno-okruzenje.pdf · 3. Razvojno okruženje Razvojna sredstva savremenih računara opšte namene

  • Upload
    lybao

  • View
    235

  • Download
    3

Embed Size (px)

Citation preview

Page 1: 3. Razvojno okruženje - es.elfak.ni.ac.rses.elfak.ni.ac.rs/es/Materijal/Pog.3-Razvojno-okruzenje.pdf · 3. Razvojno okruženje Razvojna sredstva savremenih računara opšte namene

3. Razvojno okruženje Razvojna sredstva savremenih računara opšte namene kakve su PC mašine (desktops) koriste veoma složene tehnike za prevođenje programa kreiranih na nekim od HLL-ova. Pri tome u najvećem broju slučajeva izvorni kôd se direktno prevodi u binarni image-oblik koji se zatim load-uje u mašinu radi izvršenja. U suštini, ova sofisticirana razvojna sredstva prevode izvorni kôd u relokatibilne module, ponekad koristeći, a često i nekoristeći debug i simboličke informacije koje mogu biti od koristi projektantima. Pri tome, složeni i dobro optimizirani linker-i i loader-i dinamički kombinuju ove module, i u trenutku izvršenja aplikacije preslikavaju ove module u specifične memorijske lokacije. Sa druge strane, projektanti embedded sistema ne mogu da koriste ovakve beneficije iz nekoliko razloga. Kao prvo, embedded sistem se skoro uvek bazira na jedinstvenom (specifičnom) hardveru, hardver koji u suštini ne postoji (ne egzistira kao takav) kada se razvijalo razvojno sredstvo. Kao drugo, uprkos prednosti kojom se karakteriše procesor ugrađen u razvojno sredstvo, ipak postoji neznatna razlika u mašinskim jezicima između izabranog procesora i procesora ugrađenog u razvojnom okruženju, nezavisno od toga što oba procesora pripadaju istoj familiji (procesori Intel 286, 186, 288, 188, i td.). Pored toga, deo napora koje učini projektant moraju biti usmereni ka tome da se naredi razvojnom sredstvu na koji način da prevede izvorni kôd za specifični hardver embedded sistema. To znači da projektanti embeded sistema moraju da znaju mnogo više detalja o tome: a) na koji način njihova razvojna sredstva rade; b) kako izgleda razvojno okruženje; c) na koji način se izvršavaju programi. 3.1 Radno okruženje Pored dobrog poznavanja ISA (Instruction Set Architecture) tj. procesora, da bi se kreirao efikasan embedded kôd, projektantu je dodatno potrebno da dobro poznaje i sledeće detalje:

1) na koji način sistem koristi memoriju, uključujući i detalje koji se odnose na to na koji način procesor manipuliše magacinom,

2) šta se dešava pri startup sistema, i 3) na koji način se manipuliše sa prekidima i izuzecima?

Da bi ukazali, sa nešto više detalja, na ove probleme analilziraćemo rad jednog tipičnog embedded sistema zasnovanog na procesorima iz familije Motorola 68000 (68K).

3.2. Organizacija memorije Prvu stvar sa kojom se projektant embedded sistema suočava, a tiče se rada sistema, predstavlja način na koji on vidi memoriju, i kako se koristi ta memorija. Ilustracije radi, na slici 3.1 prikazan je memorijski model procesora Motorola 68K kao jednog tipičnog reprezenta procesora koji se ugrađuju u embedded sisteme. Kao što se vidi sa slike 3.1 sve što je na levoj strani u odnosu na U/I prostor može se implementirati kao ROM, a sve što je na desnoj kao RAM.

Slika 3.1. Memorijska mapa procesorskog sistema

Page 2: 3. Razvojno okruženje - es.elfak.ni.ac.rses.elfak.ni.ac.rs/es/Materijal/Pog.3-Razvojno-okruzenje.pdf · 3. Razvojno okruženje Razvojna sredstva savremenih računara opšte namene

3.2.1 Prostor namenjen sistemu Procesori iz familije Motorola 68K (kao i veći broj drugih 32-bitnih procesora) rezervišu prvih 1024 memorijskih lokacija (256 reči) za potrebe vektorske tabele. Vektori (exception vectors) predstavljaju hard-wired adrese koje procesor koristi radi identifikacije kôda (programa) koga treba izvršiti, u trenutku kada procesor treba da manipuliše sa prekidima ili drugim izuzecima (tipični takvi izuzeci su deljenje sa nulom, ili greška zbog premašaja). Svaki vektor je dužine 4 bajta, a sistem podržava rad do 256 različitih vektora za obradu izuzetaka. 3.2.2 Prostor namenjen programu Iznad sistemskog prostora nalazi se prostor u kome se čuvaju (memorisane su) instrukcije. Praktični razlog za ovakav izbor je sledeći: Sistemski i kôdni prostor je poželjno da budu kontinualni i smešteni u jednom istiom ROM memorijskom čipu. 3.2.3 Prostor namenjen podacima Iznad kôdnog prostora egzistira ROM prostor za podatke. U ovom prostoru se čuvaju konstante kakve su poruke o greškama koje se javljaju u toku rada koje obično treba saopštiti na displeju, ili drugi literali. Iznad prostora za podatke, organizacija memorije nije više tako regularna i mnogo je zavisnija od hardverskih ograničenja dizajna. To znači da memorijski model prikazan na slici 3.1 predstavlja samo jedan ilustrativni primer kako se memorija može organizovati, ali ne mora da znači da je to i pravilo. No, nezavisno od svega, sledeća tri glavna Read/Write RAM memorijska prostora moraju egzistirati kod svakog sistema: a) magacin (stack); b) slobodan memorijski prostor (free memory); i c) heap.

• Magacin - Magacin se koristi za čuvanje traga o tekućem i svim suspendovanim kontekstima izvršenja programa. To znači da se u magacinu privremeno pamte: a) vrednosti o svim tekuće aktuelnim (live) promenljivama; i b) vrednosti adresa povratka (return addresses) za sve funkcije i prekide. Vrh magacina uobičajeno se postavlja na gornji kraj memorije, a magacin stalno raste prema nižim adresama.

• Slobodan memorijski prostor - Svim statički alociranim Read/Write promenljivama se dodeljuju lokacije u slobodnom memorijskom prostoru (free memory). Globalne promenljive predstavljaju najčešći oblik statičko alociranih promenljivih, ali se i C "static" takođe čuvaju u ovom prostoru. Bilo koja promenljiva koja se može modifikovati, a tipa je globalna promenljiva smešta se u free memoriji.

• Heap - Svi dinamičko alocirani (kreirani pomoću new ili malloc()) objekti i promenljive se čuvaju u heap-u. Obično, memorija koja preostane nakon dodele magacina kao i free memorija pridružuje se heap-u. Heap standardno povezuje strukture podataka kojima upravljaju rutine iz compiler run-time package-a. Najveći broj embedded sistema ne koristi heap.

3.2.4 Nezauzeti memorijski prostor Prekid na sredini slike 3.1 odnosi se na slobodan (nezauzet) adresni prostor koji nije pridružen bilo kojoj memoriji. Recimo, jedan tipičan embedded sistem može da ima instalirano po nekoliko megabajtova ROM prostora za instrukcije i podatke i još po nekoliko megabajtova RAM prostora. S obzirom da Motorola 68K, kao i veći broj 32-bitnih procesora, može da adresira memorijski prostor obima 16 MB pa i veći, pa zbog toga veliki deo ovog prostora obično ostaje neiskorišćen.

Page 3: 3. Razvojno okruženje - es.elfak.ni.ac.rses.elfak.ni.ac.rs/es/Materijal/Pog.3-Razvojno-okruzenje.pdf · 3. Razvojno okruženje Razvojna sredstva savremenih računara opšte namene

3.2.5 Ulazno/izlazni prostor Zadnja memorijska komponenta se odnosi na memorijsko-preslikavanje perifernih uređaja. Na slici 3.1 ovi uređaji se nalaze (locirani su) u U/I prostoru. Nasuprot nekim procesorima (kakvi su oni iz Intelove familije x86) procesori iz familije Motorola 68K ne podržavaju rad izdvojenog U/I prostora, nego memorijsko preslikanog U/I-a. Obično, radi lakšeg dekodiranja, adrese U/I uređaja su razmeštene (scattered) po memoriji na raznim lokacijama. 3.3 Startup sistema

Dobro razumevanje layout-a memorije predstavlja projektantu solidnu osnovu da korektno razume startup sekvencu. Radi lakše dalje analize usvojićemo da je program embedded uređaja već load-ovan u korektan memorijski prostor (najčešće se to radi programiranjem EPROM-a i postavljanjem tog memorijskog čipa u korektno mesto na sistemskoj ploči). Startup sekvencu čine sledeće dve faze:

• hardverska faza - aktiviranjem linije RESET procesor izvršava hardversku fazu. Namena ovog dela startup-a je da usmeri CPU da počne sa izvršenjem programa ili nekog drugog kôda koji će preneti upravljanje programu.

• softverska faza - odgovorna je za inicijalizaciju hardverskih elemenata kao i ključnih struktura podataka u memoriji.

Na primer, kada mikroprocesor Motorola 68K izađe iz stanja RESET on obavlja sledeće dve aktivnosti:

1. Pribavlja četvorobajtnu adresu koja se čuva na lokaciji 0x000000 i kopira ovu adresu u SP registar, čime se određuje početak magacina. Uobičajeno je da se SP registar inicijalizira na vrh RAM prostora tj. 0xFFFFFE, iz razloga što magacin raste naniže. Nakon toga CPU adresira četiri bajta smeštenih u memorijskim lokacijama 000004-000007 i smešta ovu 32-bitnu vrednost u programski brojač. Konačno, procesor pribavlja instrukciju na koju ukazuje stanje programskog brojača i počinje sa izvršenjem programa. Ove aktivnosti pripadaju hardverskoj fazi.

2. Početak izvršenja programa karakteriše softversku fazu. U ovom trenutku CPU je pod kontrolom softvera ali još nije spreman za izvršenje aplikacije. Umesto toga on izvršava deo kôda kojim se inicijaliziraju različiti hardverski resursi (tajmeri, kontroleri prekida, DMA kontroleri i td.) kao i strukture podataka koje se čuvaju u memoriji a koje su neophodne radi kreiranja kompletnog radnog (run-time) okruženja.

3.3.1 Ciklus odziv-na-prekid Koncepsijski posmatrano prekidi su relativno jednostavni za procesiranje. Nakon prijema INTR signala CPU "ostavlja na stranu" ono što tekuće radi, izvršava instrukcije kojima se opslužuje prekid, a zatim se ponovo vraća na izvršenje prekinutog zadatka. Kod ovakvog načina procesiranja kritičan element je sledeći: Hardver CPU-a je taj koji vodi računa o prenosu upravljanja sa jednog zadatka na drugi, kao i ponovnog povratka. Pri tome, porjektant sistema ne može da kôdira (utiče na) ovaj prenos putem kreiranja nekog memorijskog niza instrukcija iz prostog razloga što ne postoji način kojim se može predvideti trenutak kada će se zahtev za prekid javiti. I pored toga što je ovaj mehanizam prenosa skoro identičan kod svih arhitektura, ipak neke male razlike postoje. One se odnose na to kako različiti CPU-ovi vrše obradu zahteva za prekid. Ključne stavke koje se odnose na obradu prekida, a koje projektant treba da razume su:

1. Kako CPU zna gde da pronađe kôd (tj. početnu adresu) prekidne rutine? 2. Koje akcije CPU treba da preuzme kako bi zapamtio, a kasnije i obnovio "kontekst" glavnog

thread-a? 3. Kada treba dozvoliti rad prekidima?

Kao što smo napomenuli, prvih 1024 bajtova memorije je rezervisano za čuvanje exception vektora. Na odgovarajućim lokacijama u vektor tabeli nalaze se početne instrukcije za obradu izuzetaka.

Page 4: 3. Razvojno okruženje - es.elfak.ni.ac.rses.elfak.ni.ac.rs/es/Materijal/Pog.3-Razvojno-okruzenje.pdf · 3. Razvojno okruženje Razvojna sredstva savremenih računara opšte namene

Kada periferija generiše zahtev za prekid, a CPU-u je dozvoljleno da prihvata taj zahtev, tada Motorola 68K (važi i za veći broj drugih mikroprocesora) obavlja sledeće aktivnosti:

• smešta adresu naredne instrukcije prekinutog programa (povratnu adresu) u magacin, • puni početnu adresu (vektor) ISR-a (Interrupt Service Routine) iz vektorske tabele u programski

brojač, • zabranjuje rad drugim prekidima, • nastavlja sa normalnim ciklusima tipa fetch-execute, ali u ovom trenutku pribavlja instrukcije koje

pripadaju ISR-u, i • na kraju izvršenja ISR-a povratak iz prekidnog programa (ISR) u prekinuti vrši se naredbom RTE

(return from exception). 3.3.2 Pozivi funkcije i okviri magacina Kada projektant kreira neku funkciju na HLL-u, kakav je recimo, C i asemblira je, kompajler je konvertuje u potprogram na asemblerskom jeziku. Ime potprograma na asemblerskom jeziku slično je imenu funkcije na C-u sa tom razlikom što ispred imena stoji simbol "_" (donja crta ili underscore). Na primer, main() postaje _main. Na sličan način kako se funkcija na C-u main() završava iskazom return, tako se i verzija na asemblerskom jeziku završava asemblersko jezičkim ekvivalentom: RTS. Na slici 3.2 prikazana su dva potprograma FOO i BAR, jedan ugnežđen u okviru drugog. Glavni program poziva potprogram FOO koji zatim poziva potprogram BAR. Kompajler prevodi poziv BAR-a koristeći isti mehanizam kao i kod poziva FOO-a. Pri ovome je moguće obavljati automatsko smeštanje- i izbavljanje-iz magacina jer magacin se ponaša kao struktura tipa LIFO. Naime, operacijom PUSH adresa povratka se smešta u magacin, a operacijom POP se ona izbavlja iz magacina u trenutku povratka iz potprograma. Potprogram na asemblerskom jeziku poziva se naredbom JSR. Argument ove instrukcije je memorijska adresa koja ukazuje na početak potprograma. Kada procesor izvršava naredbu JSR on automatski smešta adresu naredne instrukcije pozivnog programa u magacin. Nakon toga počinje sa izvršenjem prve naredbe pozvanog programa. Na kraju pozvanog programa, obavljanjem instrukcije RTS, ponovo se vraćamo na izvršenje pozivnog programa sa one lokacije koju smo privremeno zapamtili u magacinu. Magacin se obično koristi za memorisanje lokalno promenljivih kao i argumenata funkcije. I pored toga što se smeštanje povratne adrese pozivnog programa kao i izbavljanje te adrese iz magacina obavlja po automatizmu od strane hardvera (ove aktivnosti se obavljaju u toku izvršenja naredbi JSR i RTS) kompajler je taj koji mora eksplicitno da generiše naredbe za ovakve aktivnosti na asemblerskom jeziku. Ove naredbe se koriste za manipulisanje memorijskim prostorom koji se dodeljuje lokalno promenljivim. U ovakvim situacijama različiti kompajleri koriste različite opcije. U opštem slučaju kompajler može da generiše kôd kojim se:

• smeštaju u magacin svi argumenti • poziva funkcija • alocira memorija (u magacin) za sve lokalne promenljive • obavlja zadatak dodeljen funkciji • dealocira prostor dodeljen lokalno promenljivim • obavlja povratak od funkcije ka pozivnom programu • dealocira prostor koji se koristi za čuvanje argumenata.

Skup celokupno dodeljenog prostora jednom pozivu funkcije (argumenti, povratne adrese, i lokalno promenljive) naziva se okvir magacina (stack frame). U okviru potprograma na asemblerskom jeziku okvir magacina nije ništa više od jednog lokalnog RAM bloka koji se adresira preko jednog internog registra CPU-a, nazvanog pokazivač okvira FP (frame pointer).

Page 5: 3. Razvojno okruženje - es.elfak.ni.ac.rses.elfak.ni.ac.rs/es/Materijal/Pog.3-Razvojno-okruzenje.pdf · 3. Razvojno okruženje Razvojna sredstva savremenih računara opšte namene

Slika 3.2 Potprogrami i šematski prikaz asemblersko-jezičkog potprograma

3.4 Run-time okruženje Run-time okruženje čine sve softverske strukture (nisu eksplicitno kreirane od strane programera) koje podržavaju izvršenje programa. Struktura koja povezuje okvire-magacina se može smatrati kao deo run-time okruženja. Za programere na C-u druge dve glavne komponente koje čine run-time okruženje su startup kôd i run-time biblioteka. 3.4.1 Startup kôd Startup kôd je softver koji premošćava vezu između hardverske startup faze i programa main(). Softver za premošćavanje treba da se izvrši pri svakom RESET-u, i minimalno, treba da prenese upravljanje programu main(). Trivijalna implementacija startup-a može da predstavlja asemblersko-jezički fajl koga čini samo sledeća instrukcija: JMP _main Da bi učinili ovaj kôd, koga čini samo jedna instrukcija, izvršivim, u toku startup-a, neophodno je da se pronađe način kako da se smesti adresa instrukcije JMP na memorijske lokacije 000004-000007. (Promeniti vrednost vektora izuzetka prve instrukcije u vektor tabeli koja se izvršava od strane procesora.) Standardna rešenja se ne baziraju na rešenju da se koristi direktni skok na main(). Kod realnih sistema, kada se izvršenje programa startuje po prvi put, prvo se standardno obavljaju i neke provere koje se odnose na integritet sistema, kakve su ROM checksum-test, RAM test, zatim se vrši relokacija kôda iz ROM u RAM prostor u cilju bržeg pristupa, nakon toga se obavlja inicijalizacija hardverskih resursa, a na kraju se postavlja ostalo potrebno okruženje za HLL C, pre nego što se konačno skoči na _main. Za razliku od desktop okruženja gde startup kôd ne treba nikada da se menja, kod embedded okruženja startup kôd treba da se prilagodi rešenju. Da bi učinili mogućim da se startup kôd može modifikovati najveći broj C kompajlera koji se nude na tržištu mogu automatski generisati kôd koji sadrži poseban fajl na asemblerskom jeziku u kome se nalazi startup kôd. Obično se ovaj fajl naziva crt0 ili crt1 (gde se crt odnosi na C Run Time). Ova mogućnost obezbeđuje projektantima da modifikuju startup kôd nezavisno od ostalih aktivnosti koje treba preduzeti. Na slici 3.3 prikazan je dijagram toka funkcije crt0 za HP B3640 68K familiju C kros-kompajler.

Page 6: 3. Razvojno okruženje - es.elfak.ni.ac.rses.elfak.ni.ac.rs/es/Materijal/Pog.3-Razvojno-okruzenje.pdf · 3. Razvojno okruženje Razvojna sredstva savremenih računara opšte namene

Slika 3.3 Funkcija crt0

3.4.2 Run-time biblioteka Najrestriktivnija definicija run-time biblioteke je sledeća: To je skup nevidljivih funkcija koje se koriste za podršku rada sistema kojim se pojednostavljuje generisanje kôda. Tako na primer, ako mašina ne poseduje hardver za podršku rada FP operacija, tada kompajler generiše poziv aritmetičkoj rutini koja je deo run-time biblioteke, svaki put kada se izvršava FP operacija. Smatrajmo da su rutine standardne C biblioteke deo run-time biblioteke. Eliminacijom funkcija run-time biblioteke koje se ne koriste, moguće je značajno redukovati obim programskog kôda kod embedded sistema. Takođe je moguće neke složene implementacije smanjiti uvođenjem prostih. Optimizacije (minimizacije obima kôda) se uobičajeno odnose na sledeće stavke:

a) Podrška radu FP operacijama – ako ne postoji podrška za rad FP operacijama tada proizvođač kompajlera može da ponudi fixed-point biblioteku koja se može direktno pozivati.

b) Podrška radu formatiranom izlazu (printf()) – umesto potpune podrške printf() funkciji, proizvođač može da ponudi funkcije za formatiranje specifičnih tipova kakve su, na primer, printIntAsHex(), printStr(), i druge.

c) Podrška radu dinamičkoj alokaciji (ovo se odnosi na malloc() i funkciju HLL-a C++ kakva je new) – kako će projektant primeniti dinamičku alokaciju zavisi od mnogo faktora, a ne samo od dostupnog memorijskog prostora i hardverske podrške. U principu se dinamička alokacija ne koristi kod embedded sistema.

3.5 Razmeštanje objekata Jasno je da projektanti embedded sistema treba da su u stanju da upravljaju fizičkom pozicijom (lokacijom) kôda i podataka u memoriji. Tako na primer, da bi kreirali tabelu vektora za obradu izuzetaka neophodno je da se kreira vektor ISR adresa i uslov da se početak tog vektora smesti na lokaciju 0. Na sličan način, programeri embedded sistema mora da su u stanju da smeste programske instrukcije na lokacijama gde se nalazi instaliran EPROM, a takođe da smeste globalne promenljive u adresni prostor gde se nalazi RAM. Slični izazovi postoje za startup kôd i ISR-ove.

Page 7: 3. Razvojno okruženje - es.elfak.ni.ac.rses.elfak.ni.ac.rs/es/Materijal/Pog.3-Razvojno-okruzenje.pdf · 3. Razvojno okruženje Razvojna sredstva savremenih računara opšte namene

Linker je primarno sredstvo (tool) koje se koristi za upravljanje razmeštajem kôda. U opštem slučaju, asembler kreira relokatibilne module koje linker "fiksira" na specifične fizičke adrese. Objasnimo sada šta znači pojam relokatibilni moduli i na koji način programeri embedded sistema mogu upravljati fizičkim razmeštajem objekata. 3.5.1 Relokatibilni objekti Klasičan razvojni model embedded softvera je prikazan na slici 3.4. Kao što se vidi sa slike 3.4, C ili C++ izvorni fajl zajedno sa include fajlovima kompajliraju se od strane kompajlera u izvorni fajl na asemblerskom jeziku, a zatim asembler je taj koji kreira relokatibilni objektni fajl (modul).

Slika 3.4 Razvojni proces embedded softvera

Kada asembler prevodi izvorne module u relokatibilne objektne module on manipuliše sadržajem internog brojača - nazvan lokacioni brojač - sa ciljem da čuva trag o granicama instrukcija (obim instrukcija izražen u bajtovima), relativno u odnosu na početnu adresu tog bloka. Na slici 3.5 prikazan je deo kôda na asemblerskom jeziku mikroprocesora iz familije Motorola 68K.

Slika 3.5 Deo kôda na asemblerskom jeziku

Page 8: 3. Razvojno okruženje - es.elfak.ni.ac.rses.elfak.ni.ac.rs/es/Materijal/Pog.3-Razvojno-okruzenje.pdf · 3. Razvojno okruženje Razvojna sredstva savremenih računara opšte namene

Kao što se vidi sa slike 3.5, brojač bajtova koji odgovara tekućoj vrednosti lokacionog brojača je osenčen. Brojač pokazuje na adresu instrukcije u ovom kôdnom bloku. Kod jednostavnih razvojnih okruženja, projektant koristi specijalne pseudo-instrukcije na asemblerskom jeziku kako bi razmestio objekte na pojedine lokacije, kao na primer, ORG 200H koja uslovljava da početna adresa modula bude 512. Kada se koriste HLL-ovi, za upravljanje razmeštajem, potrebno je koristiti neke druge mehanizme. Rešenje pozicioniranja sastoji se u tome da asembler generiše relokatibilne module. Pri tome, svaki relokatibilni modul se prevodi na takav način kao da počinje sa memorijske lokacije 0. Kada asembler pripremi modul, on takođe priprema simbol-tabelu koja pokazuje koje vrednosti u modulu treba promeniti ako se modul premesti na neku drugu lokaciju koja je različita od 0. Pre nego što se moduli load-uju radi izvršenja, linker ih relocira. Naime, linker podešava sve poziciono-osetljive vrednosti na takav način da budu odgovarajuće, tj. da pozicione vrednosti (adrese) odgovaraju stvarnoj poziciji modula u memoriji. Skupovi instrukcija savremenih procesora često sadrže specifično projektovane instrukcije koje pojednostavljuju posao linker-a, kao na primer, "jump-relative" instrukcije za koje nije potrebno podešavanje. Često kompajlerima i linker-ima ovih mašina se može narediti da generišu poziciono-nezavisne kodove, koji ne zahtevaju podešavanje, nezavisno od toga gde će se kôd smestiti u memoriji. Relokatibilni moduli (fajlovi) referenciraju (obraćaju se) funkcije u drugim modulima, tako da, na prvi pogled, postoji Pandorina kutija međusobno povezanih funkcijskih poziva i memorijskih referenciranja. Pored podešavanja internih referenciranja na aktuelne lokacije, linker je takođe zadužen za rešavanje ovih inter-modularnih referenciranja kao i kreiranje kôdnog bloka koji se može load-ovati na specifičnu lokaciju (memorijsku adresu) sistema. Kao zaključak bi mogli da kažemo sledeće:

1) Relokatibilni moduli su važni iz više razloga. Ono što je najvažnije je to da prgramerima embedded sistema, relokatibilni moduli pojednostavljuju fizički razmeštaj kôda generisanog od strane HLL-a, i omogućavaju individualnim modulima da se nezavisno ažuriraju i kompajliraju.

2) Kod sistema opšte-namene, relokatibilni moduli imaju tu dobru stranu da pojednostavljuju upravljanje memorijom (omogućavajući individualnim programima da se pune u bilo koju dostupnu memorijsku sekciju (deo) bez rekompilacije), kao i da olakšavaju korišćenje deljivih, unapred rekompajliranih biblioteka.

3.5.2 Korišćenje linkera Ulazi u linker su: a) relokatibilni objektni moduli; i b) komandni fajl linker-a. Komandni fajl linker-a pruža projektantu mogućnost da u potpunosti kontroliše na koji će se način kôdni moduli međusobno povezati i kako se kreira konačna slika. Komandni fajl linker-a je ključni elemenat u ovom procesu i važan je diferencijator u odnosu na to kako se piše kôd za embedded sisteme ili kôd za desktop PC-ove, kao mašine opšte namene. Komandni fajl linker-a je korisničko kreirani tekstualni fajl koji ukazuje linker-u na koji način treba međusobno povezati relokatibilne fajlove. Linker-i koriste programske sekcije. Programska sekcija predstavlja kôdni-blok ili blok-podataka koji je logički različit u odnosu na druge sekcije i može se opisati svojim sopstvenim lokacionim brojačem. Sekcije imaju različite atribute koji ukazuju linker-u kako se ti atributi mogu koristiti. Tako na primer, sekcija može biti:

• kôd programa • kôd podataka • mešavima kôda i podataka • podaci smešteni u ROM-u

Listing na slici 3.6 prikazuje tipične linker komande za mikroprocesore iz familije Motorola 68K, a značenje linker komandi je objašnjeno na slici 3.7.

Page 9: 3. Razvojno okruženje - es.elfak.ni.ac.rses.elfak.ni.ac.rs/es/Materijal/Pog.3-Razvojno-okruzenje.pdf · 3. Razvojno okruženje Razvojna sredstva savremenih računara opšte namene

CHIP 68000 LISTMAP INTERNALS, PUBLICS, CROSSREF COMMON COMSEC=$1000 ORDER SECT2, SECT3, COMSEC PUBLIC EXTRANEOUS=$2000 NAME TESTCASE PAGE SECT2 FORMAT IEEE *LOAD-ovati prva dva modula LOAD Lnk68ka.obj, lnk68kb.obj *LOAD-ovati poslednji modul LOAD lnk68kc.obj END

Slika 3.6 Primer komandnog fajla linker-a CHIP Specificira ciljni mikroprocesor. Ova komanda određuje kako će se sekcije poravnjati sa

tačke gledišta memorijskih adresnih granica, i u zavisnosti od specificiranog mikroprocesora, koliko je memorije dostupno. Konačno, ova komanda određuje ponašanje određenih procesorsko specifičnih adresnih načina rada.

LISTMAP Generiše listing simbol-tabele kako za lokalne tako i eksterne simbol-definicije. Ova komanda takođe uzrokuje da se ovi simboli smeste u izlazni objektni modul tako da debager kasnije može simbolima da pridruži adrese. Simbol-tabela prikazuje simbole zajedno sa njihovim konačnim apsolutnim adresnim lokacijama. Moguće je zatim analizirati izlaz link-map-e i odrediti da li su svi moduli korektno povezani, kao i odrediti da li se nalaze u memoriji gde je projektant zamislio da trebaju biti. Kada linker uspešno obavi svoj zadatak, tada sve adrese su podešene na korektne konačne vrednosti, a takođe i svi link-ovi ili veze između modula su razrešeni.

COMMON; nazvan COMSEC

Smešten je na heksadecimalnoj početnoj adresi 1000 ($ označava heksadecimalnu vrednost). Linker smešta sve COMMON sekcije različitih modula sa istim imenom na istom mestu u memoriji. COMMON sekcije se u opštem slučaju koriste za programske promenljive koje se čuvaju u RAM-u, kao globalne promenljive.

ORDER Specificira redosled po kome se sekcije zajednički povezuju u izvršivu image. PUBLIC Specificira apsolutnu adresu, heksadecimalnu 2000, za promenljivu EXTRANEOUS. NAME TEST CASE

Specificira ime fajla konačnog izlaznog modula.

PAGE Specificira da naredna sekcija počne na granici stranice, tj. da početna adresa bude multipl od 256. Nakon čitanja PAGE komande, svaka sub-sekcija, ili modul, specificirane sekcije se poravnjava na granicama stranice. U konkretnom primeru (slika 3.6) SECT 2 startovaće na narednoj dostupnoj granici stranice.

FORMAT Specificira izlaz fajl formata. U konkretnom slučaju je to format IEEE-695, koji predstavlja standardni industrijski fajl format. Drugi format je Motorola S-Record fajl, koji je ASCII kôdirani fajl i čitljiv je od strane korisnika. Zapisi se uobičajeno koriste za punjenje kôda u uređaj za programiranje ROM-ova.

LOAD Puni naredna tri specificirana objektna fajla. END Označava kraj objektnih fajlova.

Slika 3.7. Komande linker-a