Оперативни системи 1 Вeжбе 1 Архитектура 8086

Slides:



Advertisements
Similar presentations
Programming 8086 – Part IV Stacks, Macros
Advertisements

Lect 3: Instruction Set and Addressing Modes. 386 Instruction Set (3.4) –Basic Instruction Set : 8086/8088 instruction set –Extended Instruction Set :
Flow Diagram: Push flags, CS, IP Pop IP,CS,flags Push AX,BX,CX,DX,ES,DS,SI,DI,BP POP BP,DI,SI,DS,ES,DX,CX,BX,AX.
Stack Memory H H FFFFF H FFFFE H SS 0105 SP 0008 TOS BOS BOS = FFFF = 1104F H H 1104F H.
Lect 4: Instruction Set and Addressing Modes. 386 Instruction Set (3.4)  Basic Instruction Set : 8086/8088 instruction set  Extended Instruction Set.
Implementing function/ procedure calls (in Pascal and C)
ДАВАЧИ ПОМЕРАЈА 2. Садржај  Синхроуређаји  Разлагачи  Индуктосини  Енкодери  Дифракционе решетке  Двобрзински мерни системи  Двоположајни давачи.
Strings, Procedures and Macros
Module R3 Process Scheduling. Module R3 involves the creation of a simple “Round Robin” dispatcher. The successful completion of this module will require.
ECE291 Computer Engineering II Lecture 3 Dr. Zbigniew Kalbarczyk University of Illinois at Urbana- Champaign.
University of Tehran 1 Microprocessor System Design Omid Fatemi Machine Language Programming
Multi-module programming. Requirements of an assembly language module when it is linked with another module PUBLIC directive - it exports to other modules.
Assembly Language Data Movement Instructions. MOV Instruction Move source operand to destination mov destination, source The source and destination are.
BITS Pilani Pilani Campus Pawan Sharma Lecture /12/ EEE /INSTR/CS F241 ES C263 Microprocessor Programming and Interfacing.
Microprocessors CSE- 341 Dr. Jia Uddin Assistant Professor, CSE, BRAC University Dr. Jia Uddin, CSE, BRAC University.
КОНКУРС МИНИСТАРСТВА ЗА ТЕЛЕКОМУНИКАЦИЈЕ И ИНФОРМАЦИОНО ДРУШТВО „Дигитални час“ Основна школа “Јован Поповић “ Сусек одељење у Баноштору Аутор: Ђурђица.
Microprocessors CSE- 341 Dr. Jia Uddin Assistant Professor, CSE, BRAC University Dr. Jia Uddin, CSE, BRAC University.
ΜComputer Structure μProcessor Memory Bus System I/O Ports.
Кеш меморијa Приципи рада кеш меморија Величина кеша
Instruction set Architecture
Format of Assembly language
COURSE OUTCOMES OF MICROPROCESSOR AND PROGRAMMING
Instruksi Set Prosesor 8088
ADDRESSING MODES.
Microprocessor and Assembly Language
Chapter 4 Data Movement Instructions
Assembly IA-32.
ADDRESSING MODES.
ОДРЖАВАЊЕ И ЗАШТИТА СИСТЕМА
Symbolic Instruction and Addressing
Матична Плоча Миле Станковић
Методика наставе рачунарства
Архитектура рачунарских система
Petlje WHILE – WEND.
Introduction to Assembly Language
שפת סף וארכיטקטורה של מעבד 8086
Stack and Subroutines Module M17.1 Section 11.2.
ОСНОВНИ ЕЛЕМЕНТИ ГРАФИЧКОГ ИНТЕРФЕЈСА
CheckBox RadioButton RadioGroup
ارايه دهنده : حسن عسكرزاده
Коначни аутомати.
Internet mreže, FTN - KZI
Програмски језик C Структура програма, типови података,
ОСНОВИ ИНФОРМАЦИОНИХ ТЕХНОЛОГИЈА
KREIRANJE OBJEKATA.
8086 Registers Module M14.2 Sections 9.2, 10.1.
Uvod u programiranje - matematika – X predavanje
Подешавање радног окружења програма Microsoft Word
Reference ćelije i opsega
Interrupt Mechanism Interrupt Compared With Procedures Call MyProc
Struktura MAC adrese i Ethernet okvira
Morgan Kaufmann Publishers Computer Organization and Assembly Language
Organizacija sistema zasnovana na
Symbolic Instruction and Addressing
Дистрибуиране базе података
M-datoteke.
СОФТВЕР.
Ključne reči,identifikatori, konstante i promenljive
Аритметичке и логичке операције
Оператор надовезивања
Архитектура и програмирање микропроцесора Intel 8086 (3)
Глобални барометар корупције 2009
Do While ... Loop struktura
(The Stack and Procedures)
Symbolic Instruction and Addressing
Computer Architecture CST 250
Chapter 6 –Symbolic Instruction and Addressing
Process.
Intel 8086.
Chapter 8: Instruction Set 8086 CPU Architecture
Presentation transcript:

Оперативни системи 1 Вeжбе 1 Архитектура 8086 Листа предмета: ir2os1@lists.etf.rs Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Увод у архитектуру 8086 16-битни 2-адресни микропроцесор Адресибилна јединица бајт Подаци 1 или 2 бајта Нижи бајт на нижој меморијској локацији Регистри: сегментни општенемeнски индексни базни регистар BP и показивач на стек SP Стек: Расте ка нижим адресама SP указује на последњу заузету локацију на врху стека 16-битни микропроцесор значи да су регистри 16-битни и да АЛУ јединица може одједном да ради са подацима максималне дужине 16-бита. У ужем смислу би требала да је и магистрала података 16 бита, па да према томе и адресибилна јединица буде 16 бита. Такође би и адресна магистрала била 16 бита широка. То међутим није тако. Процесор 8086 има адресибилну јединицу ширине 8 бита иако је магистрала података 16, док је адресна магистрала широка 20 бита. Микропроцесор значи да постоји само један процесор на чипу. Инструкцијски сет погледати овде: http://www.electronics.dit.ie/staff/tscarff/8086_instruction_set/8086_instruction_set.html Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Сегментни регистри CS – код сегмент, SS – стек сегмент, DS – сегмент података и ES – екстра сегмент за податке Користе се за формирање адресе: адреса је 20-битна састоји се од: сегмента – SEG (16 бита) и офсета (померај) – OFF (16 бита) физичка адреса је 20 бита и рачуна се: 0х10 * SEG + OFF сегмент је увeк један од 4 сегментна регистра Напомене: ови сегменти немају никакве везе са виртуелним адресирањем које се налази код модерних процесора примeтити да се неке физичке адресе могу добити комбинацијом више различитих парова сегмената и офсета Relokatibinost programa je još jedan bitan značaj segmentnih registara, osim većeg opsega memorijskih adresa. CS : Ne može se direktno menjati, Automatski se menja prilikom far jump, far call ili far return instrukcija Omogućava pristup do 64KB koda Pozdrazumevani ofsetni registar: * CS:PC (IP  PC) SS: Može se direktno menjati POP instrukcijom Pozdrazumevani ofsetni registri: * SS:SP * SS:BP DS: -Može se direktno menjati LDS instrukcijom (učitava far pointer) Primer: LDS AX, m m DW 1234h DW 5678h Izlaz: AX = 1234h DS = 5678h - Podrazumevani ofsetni registri: * DS:BX * DS:SI * DS:DI ES: -Može se direktno menjati LES instrukcijom -Obično služi kao ekstra segment za podatke Оперативни системи 1, ЕТФ 2017. 3

Општенамeнски регистри AX - акумулатор BX - базни регистар CX - бројачки регистар DX - регистар података Сваки по 16 бита Сваки се може посматрати као два 8-битна: AX -> AH (виши бајт) и AL (нижи бајт) BX -> BH (виши бајт) и BL (нижи бајт) CX -> CH (виши бајт) и CL (нижи бајт) DX -> DH (виши бајт) и DL (нижи бајт) Примeр: mov AX,1234h ; isto što i 0х1234 na C-u AH AL 12h 34h AX – akumulator, mora da bude jedan od registara u aritmetičko logičkim instrukcijama; rezultat potprograma se vraća kroz ovaj registar BX – bazni registar, pristup podacima u memoriji – jedino ovaj opštenamenski registar može biti korišćen za pristup memoriji (unutar zagrada [] ) CX – brojački registar, implicitno se dekremetrira/inkremetrira prilikom izvršavanja REP ili LOOP instrukcije DX – registar podataka, koristi se, recimo, kao pomoćni registar prilikom vraćanja 32-bitne vrednosti iz potprograma. Оперативни системи 1, ЕТФ 2017.

Индексни и базни регистри Индексни: SI i DI, Сваки по 16 бита Користе се при индексном адресирању (приступ елементима низа) Примeр: mov AX, niz[SI] Базни регистар за приступ стеку: BP 16 бита Користи се за приступ стеку (приступ стварним аргументима и локалним промeнљивим процедуре) SI – source index DI – destination index Primer2: MOV AX, DS:[SI] MOV DS:[SI], ES:[DI] MOV ES:[DI], AX BP – base pointer MOV AX, [BP + 2] ; BP ofset u odnosu na SS Od svih dostupnih registara, samo registri SI, DI, BP i BX mogu biti korišćeni za pristup memoriji (samo se oni mogu naći unutar [] zagrada, tj. ovi registri se koriste kod reg. ind. i reg. ind. sa pomerajem adresiranja). Оперативни системи 1, ЕТФ 2017.

Стек позива потпрограма (1/2) Без BP Са BP SP Više adrese Sačuvani registri i lokalne promenljive Privremeni podaci (međurezultati, privremeni pozivi) Okvir izvršavanja tekuće procedure (stack frame) Parametri Povratna adresa Menja se tokom izvršavanja SP Sačuvani registri i lokalne promenljive Parametri Povratna adresa Privremeni podaci (međurezultati, privremeni pozivi...) Okvir izvršavanja tekuće procedure (stack frame) BP [BP+n] [BP-n] BP ukazuje na fiksnu poziciju na steku tekuće procedure, dok SP ukazuje na kraj steka koji može da varira zbog čuvanja privremenih podataka (međurezultati, pozivi potprograma i slično). Prednosti upotrebe BP - ne moramo da vodimo računa koliko je narastao stek, već možemo relativno u odnosu na bp da pristupamo lokalnim promenljivima ili prosleđenim parametrima. Зашто BP? Зар није довољан SP? Оперативни системи 1, ЕТФ 2017. 6

Стек позива потпрограма (2/2) C конвенција при позиву потпрограма: SP Sačuvani registri i lokalne promenljive Parametri Povratna adresa Privremeni podaci (međurezultati, privremeni pozivi...) Postavlja pozivajuća procedura (caller) BP [BP+n] [BP-n] Stari BP Postavlja pozvana procedura (called procedure) Više adrese Stek raste mySub: ; Start of procedure push bp mov bp, sp sub sp, n ; reserve n bytes ; of local storage push reg1 ; save registers push reg2 ... ; do some processing ... pop reg2 ; just the opposite pop reg1 add sp, n mov sp, bp pop bp ret ; we are done. Jedna moguća konvencija pri pozivu podprograma; Parametri se stavljaju na stek u obrnutom redosledu od onog navedenog u deklaraciji f-je. (npr. za listu parametara (a, b, ...) - a treba da bude na fiksnoj poziciji 6, b 8 itd. To je takozvana C konvencija. Ovu konvenciju je uglavnom moguće promeniti prilikom kompajliranja. Tako BCC kompajler nudi i Pascal konvenciju, koja stavlja parametre u obrnutom poretku od navedenog. U konvenciju poziva ne spada samo redosled smeštanja parametara na stek, već i podele odgovornosti između pozivaoca i pozvane funkcije, kako se prosleđuju parametri (preko steka ili registara) i kako se vraća rezultat potprograma. U C konvenciji, rezultat se vraća putem registra al, ax ili dx:ax u slučaju da je vrednost 8, 16 ili 32 bita, respektivno, dok se parametri prosleđuju putem steka. Напомена: Параметри се стављају на стек у обрнутом редоследу од оног наведеног при декларацији функције Оперативни системи 1, ЕТФ 2017. 7

Како се потпрограму прослеђују параметри? Потпрограм написан на C-у: int fun(int a){ return a; } Исти потпрограм на асемблеру: fun proc push BP mov BP, SP mov AX, [BP+6] pop BP ret fun endp

Како се потпрограму прослеђују параметри? BP АХ = 0х1234 Стек: xx +7 12 виши бајт на вишој адреси +6 34 нижи бајт на нижој адреси +5 retCSh h – high byte +4 retCSl l – low byte +3 retPCh +2 retPCl +1 oldBPh +0 oldBPl fun proc push BP mov BP, SP mov AX, [BP+6] pop BP ret ... push 1234h call fun add SP, 2 Напомена: Претпоставља се huge mem. model SP Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Меморијски модел Меморијски модели подржани од стране највећег броја компајлера су: tiny, small, medium, compact, large и huge Одређују сегментираност програма у меморији - код,стек,подаци Утичу на величину програма Mоже да се бира приликом превођења Модели које ћемо користити су small или huge Приликом позива потпрограма на стеку се чува : small модел - офсетни део повратне адресе (16b) huge модел - сегментни и офсетни део повратне адресе(32b), респективно Оперативни системи 1, ЕТФ 2017.

Задатак 1 Написати програм на програмском језику C који ће помоћу једне функције бесконачно исписивати неки текст. Решење може да буде некоректно у смислу да ће оперативни систем у коначном времену пријавити грешку у извршавању програма и прекинути његово извршавање. Није дозвољено коришћење петљи. #include<stdio.h> void a(){ printf("...\n"); a(); } void main(){ BP Стек: (у једном реду једна реч – 2B) xx retCSend_main retPCend_main oldBP_main retCSend_a retPCend_a oldBP_a1 retCSend_a retPCend_a oldBP_a2 ... Шта је проблем? SP

Оперативни системи 1, ЕТФ 2017. Задатак 2 Написати програм на програмском језику C који ће бесконачно понављати исписивање неког текста. Није дозвољено користити петље и програм мора бити исправан, тј. да оперативни систем никада не пријави грешку за тај програм. Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Решење #include <stdio.h> int i; void a(){ //cuva pov. adr. asm{ push ax mov ax, [bp]+2 mov i,ax pop ax } void b(){ //menja pov. adr. asm{ push ax mov ax,i mov [bp]+2,ax pop ax } int main(){ a(); printf("Izmedju a i b.\n"); b(); return 0; program se prevodi pomoću bcc kompajlera koji se može skinuti sa sajta predmeta bcc –ms –Ic:\bc31\include –Lc:\bc31\lib program.cpp pogledati opcije poziva kompajlera iz komandne linije u uputstvu za Borland C++, https://archive.org/details/bitsavers_borlandborn3.1ProgrammersGuide1992_17439947 printf_OFFSET BP_main AX_old return_OFFSET BP_main AX_old i: printf_OFFSET Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Задатак 3. Написати програм за процесор 8086 који треба да изврши неки потпрограм, али тако да се нигдe у коду не види позив тог потпрограма. Оперативни системи 1, ЕТФ 2017.

Решење – варијанта 1 На почетку сваке функције: push BP mov BP, SP Решење – варијанта 1 На почетку сваке функције: push BP mov BP, SP unsigned int SP_f, SP_main; unsigned int stek_f[1024]; void dispatch1() { asm { mov SP_main, sp //cuva sp od main mov sp, SP_f // restauira sp od f } void dispatch2() { mov SP_f, sp //cuva sp od f mov sp, SP_main // restauira sp od main На крају сваке функције: pop BP ret void f() { // kod funkcije // ... // kod za izlazak iz funkcije: dispatch2(); } void main() { stek_f[1023] = FP_OFF(f) SP_f = FP_OFF(stek_f+1022); dispatch1(); stek_f+1023 stek_f SP_main SP_f xx PC_main_} BP_main ... f //adresa funkcije f SP BP PC FP_OFF(f) dohvata offset adrese f-je f FP_OFF() makro se koristi za racunanje ofsetnog dela adrese far pokazivaca. Dakle, vraca ofsetni deo prosledjene adrese (pokazivaca).

Решење – варијанта 1 Извршава се код функције unsigned int SP_f, SP_main; unsigned int stek_f[1024]; void dispatch1() { asm { mov SP_main, sp //cuva sp od main mov sp, SP_f // restauira sp od f } void dispatch2() { mov SP_f, sp //cuva sp od f mov sp, SP_main // restauira sp od main void f() { // kod funkcije // ... // kod za izlazak iz funkcije: dispatch2(); } void main() { stek_f[1023] = FP_OFF(f); SP_f = FP_OFF(stek_f+1022); dispatch1(); stek_f+1023 stek_f SP_main SP_f PC На почетку сваке функције: push BP mov BP, SP xx PC_main_} BP_main ... f //adresa funkcije f PC se ne moze promeniti direktno! SP BP На крају сваке функције: pop BP ret PC_f_}

Решење – варијанта 2 unsigned int temp; void f(); void dispatch1() { asm { pop temp push OFFSET f push temp } void f() { // kod funkcije // ... void main() { dispatch1(); temp: BP_main SP xx PC_main_} BP_main f //adresa funkcije f Prevodjenje programa bcc kompajlerom iz komandne linije: bcc -ms -2 program.cpp // opcija -2 je potrebna zbog koriscenja OFFSET kljucne reci

Оперативни системи 1, ЕТФ 2017. Задатак 4 За процесор 8086 и код написан на програмском језику C, омогућити да се функције извршавају конкурентно, а да се прелазак са функције на функцију обавља помоћу корутина. Сматрати да се користе само регистри АX,BX,CX и DX. Остале занемарити. Регистре чувати на стеку. Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Решење (1/5) Корутина Једна нит се експлицитно одриче процесора у корист друге нити Потребно је сачувати контекст, како би касније могао да се рестаурира Контекст процесора (processor execution context) Све вредности из процесорских регистара које је потребно сачувати како би се извршавање наставило од места напуштања Контекст чинe следеће информације: Место у програму на коме се стало – CS:IP Подаци у процесору – регистри опште намене Локални подаци потпрограма и “траг” извршавања – све на стеку – SP Промена контекста (context switch) Прелазак са извршавања једног процеса на други Приликом промене контекста је потребно: Сачувати контекст који се напупшта Повратити (рестаурирати) контекст на који се прелази Ilustracija – zadatak iz matematike, zvoni tel., ako se odmah javimo ne znamo gde smo stali, zato prvo zapisemo medjurezultat. Korutine su funkcije sa posebnim stekom i kontekstom procesora. Lice na niti, ali za rayliku od njih, cak i da postoji vise procesora, samo jedna korutine se u jednom momentu izvrsava, za razliku od niti koje mogu da se tada izvrsavaju u paraleli (fizicki u istom momentu). Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Решење (2/5) Претпоставити да је потребно извршити следећи код: running->sp = SP; // čuvanje SP registra Гдe је: sp поље PCB структуре (дате на следећем слајду) SP регистар На језику С у општем случају није могуће приступити жељеном регистру Зато се умећу сегменти асемблерског кода Асемблерски еквивалент горе наведеној наредби је asm{ mov BX, running // BX = running mov [BX], SP // [BX] = SP - ind. reg. adresiranje } Примeтити да се регистар BX користи за адресирање, па се на почетку његов садржај мора привремено сачувати (нпр. на стеку) Оперативни системи 1, ЕТФ 2017.

Решење (3/5) При позиву функције _dispatch() на стек ће се ставити повратна адреса. То је адреса прве инструкције после позива _dispatch() и уједно и адреса од које треба наставити прекинуту нит. По уласку у функцију, наилази се на прве две инструкције сваке функције: push BP mov BP, SP Као резултат прве инструкције на стеку је сачувана вредност BP која је коришћена у прекинутој нити и која ће се користити опет по повратку у ту нит. // zad4.cpp #include <stdio.h> #include <dos.h> struct PCB{ unsigned sp; unsigned* stack; }; PCB *p[3]; PCB* running; int nextThread; //makro #define dispatch(x) { \ nextThread = x; \ _dispatch(); \ } void _dispatch(){ asm { // Cuva registre na steku. push ax // Sta bi se desilo da ne cuvamo AX? push bx push cx push dx mov bx, running // upisuje adresu mem. lok. mov [bx], sp // cuva sp } running = p[nextThread]; asm { mov bx, running mov sp, [bx] // restauira sp pop dx // restauira podatke pop cx pop bx pop ax Чувају се и 4 регистра (тако је речено у поставци задатка). У општем случају, неопходно је сачувати све регистре осим PC (већ сачувано при позиву функције), BP (већ сачуван првом инструкцијом функције f()) и SP (биће сачуван у PCB). Чува се показивач на стек. Инструкције: mov BX, running mov [BX], sp су еквивалентне са C кодом: running->sp = SP //SP je registar running је показивач на PCB структуру нити која се тренутно извршава. Да би се умeсто нити, која се извршавала до позива dispatch() наставила нова нит, неопходно је поставити да running показује на PCB те нове нити. У овом задатку је претпостављено да се нова нит одрeђује уписом одговарајуће вредности у nextThread. Рестаурација стека нове нити: SP = running->sp; Рестаурација остатка контекста: -прво регистри DX, CX, BX и AX -рестаурација BP са pop BP -рестаурација PC са ret Pitati zašto ne čuvamo stek segment prilikom promene konteksta? Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Решење (4/5) // funkcija koju izvrsava nit 1 void a() { for (int i = 0; i < 3; ++i) printf("U a() %d\n",i); asm mov ax, 7 dispatch(2); asm mov i, ax printf(" u a() ax = %d\n",i); for (i = 0; i < 3; ++i) printf("U a() %d\n",i); } // funkcija koju izvrsava nit 2 void b() { for (int i = 0; i < 3; ++i) printf("U b() %d\n",i); asm mov ax, 2 dispatch(1); for (i = 0; i < 3; ++i) printf("U b() %d\n",i); dispatch(0); } Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Решење (5/5) void createThread (PCB * newPCB, void (*body)()) { unsigned* st = new unsigned[1024]; unsigned newPC = FP_OFF(body); st[1023] = newPC; // upisuje se rec - int // pocetni kontekst //(proizvoljne vrednosti) // st[1023-1018] = {PC,BP,AX…DX} newPCB->sp = FP_OFF(st+1018); newPCB->stack = st; } void delete_all() { delete [] p[1]->stack; delete [] p[2]->stack; delete p[0]; delete p[1]; delete p[2]; int main() { p[1] = new PCB(); createThread(p[1], a); printf("napravio a\n"); p[2] = new PCB(); createThread(p[2], b); printf("napravio b\n"); p[0] = new PCB(); running = p[0]; dispatch(1); printf("Kraj.\n"); delete_all(); return 0; } Prevodjenje programa bcc kompajlerom iz komandne linije: bcc -ms –Ic:\bc31\include –Lc:\bc31\lib zad4.cpp Pretpostavka je da je bc31 folder smesten u c:\ . Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Задатак 5 Рeшити претходни задатак, али тако да се сви регистри чувају у PCB. struct PCB{ // pomeraj u odnosu na poč. adresu strukture unsigned pc; // +0 unsigned sp; // +2 unsigned bp; // +4 unsigned ax; // +6 unsigned bx; // +8 unsigned cx; // +10 unsigned dx; // +12 - izraženo u bajtovima ... }; Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Решење (1/3) Потребно извршити следећи код: running->ax = AX; // čuvanje AX registra Гдe је: ах поље PCB структуре (дате на следећем слајду) АХ регистар На језику С у општем случају није могуће приступити жељеном регистру Зато се умећу сегменти асемблерског кода Асемблерски еквивалент горе наведеној наредби је asm{ mov BX, running // BX = running mov BX[6], AX // [BX+6] = AX - indirektno reg. } // adr. sa pomerajem - Примeтити да се BX користи за адресирање, па се на почетку његов садржај мора привремено сачувати (нпр. на стеку) Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Решење (2/3) Рестаурација контекста Чување контекста void _dispatch() { asm { push bx mov bx, running mov bx[6], ax // ax pop WORD PTR [bx+8] // bx mov bx[10], cx // cx mov bx[12], dx // dx pop WORD PTR [bx+4] // bp pop WORD PTR [bx] // pc mov bx[2], sp // sp } running=p[nextThread]; asm { mov bx, running mov sp, bx[2] // sp push WORD PTR [bx] // pc push WORD PTR [bx+4] // bp mov ax, [bx+6] // ax push WORD PTR [bx+8] mov cx, [bx+10] // cx mov dx, [bx+12] // dx pop bx // bx } struct PCB{ pomeraj unsigned pc; +0 unsigned sp; +2 unsigned bp; +4 unsigned ax; +6 unsigned bx; +8 unsigned cx; +10 unsigned dx; +12 ... }; WORD PTR[bx+4] – kažemo da stavljamo na stek reč, a ne jedan bajt. Ako želimo eksplicitno da kažemo da želimo da stavimo bajt, pišemo BYTE PTR. Zapis bx[6] je isto što i [bx + 6] i isto što i ds:[bx + 6]. I jedno i drugo je registarsko indeirektno adresiranje sa pomerajem. Напомена: WORD PTR [bx+...] – означава да се приступа речи, а не бајту Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Решење (3/3) void createThread(PCB *newPCB, void (*body)()) { unsigned* st = new unsigned[1024]; newPCB->pc = FP_OFF(body); // stek je sada prazan newPCB->sp = FP_OFF(st+1024); newPCB->bp = FP_OFF(st+1024); newPCB->stack = st; } Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Задатак 6 Изменити корутину из задатка 4. тако да се избор нове нити ради помоћу метода класе Scheduler: void Scheduler::put(PCB *); Додаје нит у листу кандидата за извршавање PCB* Scheduler::get(); Дохвата следећу нит из листе спремних процеса Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Решење void _dispatch(){ asm { // cuva registre sa podacima na steku push ax push bx push cx push dx mov bx, running mov [bx], sp // cuva sp } Scheduler::put(running); running = Scheduler::get(); asm { mov sp, [bx] // restauira registar sp pop dx // restauira registre sa podacima pop cx pop bx pop ax Чување контекста до сада извршаване нити Рестаурација контекста нити која се наставља Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Задатак 7 Написати универзалну корутину dispatch() коришћењем функција setjmp и longjmp. Функција setjmp прихвата показивач на бафер у којем чува тренутни контекст и враћа 0. Функција longjmp прихвата два параметра. Први параметар је показивач на структуру која садржи раније сачувани контекст (са setjmp) и који сада треба рестаурирати. Други параметар је вредност коју функција треба да врати (размислити где ће бити коришћена враћена вредност). Potpisi setjmp i longjmp - setjmp.h zaglavlje. setjmp() cuva kontekst u baferu koji je prosledjen kao prvi parametar (slicno kao u zadatku 5). Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Решење void dispatch (){ if (setjmp(running->context) == 0) { Scheduler::put(running); running = Scheduler::get(); longjmp(running->context,1); } else { return; } dispatch() – povratak iz f-je, na drugom steku od trenutka čuvanja konteksta pomoću setjmp(), do trenutka povratka pomoću longjmp(), izvršavanje u kome je setjmp() ne sme da se vrati iz funkcije koja neposredno okružuje poziv setjmp(), jer bi se time stek narušio, pa povratak pomoću longjmp() dovodi do kraha sistema, zato sto se na steku pamti kontekst do te funkcije u kojoj je pozvana setjump i zapamti se pozicija sp, pa ako se vratimo pre poziva longjump, moze sa steka da skine nesto i da onda zapamceni sp ukazuje na “smece”. Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Напомене Део функције dispatch() иза позива setjmp(), а пре позива longjmp(), ради и даље на стеку претходнe текуће нити (позиви функција класе Scheduler). Тек од позива longjmp() прелази се на стек нове текуће нити. Ово није никакав проблем, јер тај део представља "ђубре" на стеку изнад границе која је запамћена у setjmp(). Приликом повратка контекста претходне текуће нити, извршавање ће се наставити од запамћене границе стека, испод овог "ђубрета". U standardnoj biblioteci jezika C (pa time i C++) definisane su dve funkcije koje obezbeđuju koncept korutina. Ove funkcije "sakrivaju" neposredno baratanje samim registrima procesora, pa se njihovim korišćenjem može dobiti potpuno prenosiv program. Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Напомене Извршавање наставља са места након позива setjmp() (линија if у примеру*), с тим да сада изгледа као да је setjmp() вратила ону вредност која је достављена позиву longjmp() (то мора бити вредност различита од 0), самим тим вредност АX регистра је измењена – проблем код асинхроног преузимања. Од тренутка чувања контекста помоћу setjmp(), до тренутка повратка помоћу longjmp(), извршавање у коме је setjmp() не сме да се врати из функције која непосредно окружује позив setjmp(), јер би се тиме стек нарушио, па повратак помоћу longjmp() доводи до краха система. *Pozivom setjump se nije izvrsio i if. Prvo se poziva setjmp i pri tome se čuva povratna adresa koja odgovara instrukciji provere vrednosti koju vraća setjump sa nulom. Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Задатак 8 Имплементирати функције setjmp и longjmp тако да раде на начин описан у претходном задатку: " Функција setjmp прихвата показивач на бафер у којем чува тренутни контекст и враћа 0. Функција longjmp прихвата два параметра. Први параметар је показивач на структуру која садржи раније сачувани контекст (са setjmp) и који сада треба рестаурирати. Други параметар је врeдност коју функција треба да врати. " Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Решење (1/3) struct cnt_buf { // pomeraj unsigned sp; // +0 unsigned ax; // +2 unsigned bx; // +4 unsigned cx; // +6 unsigned dx; // +8 unsigned pc; // +10 unsigned bp; // +12 }; struct PCB { cnt_buf* context; unsigned* stack; unsigned _setjmp(cnt_buf *b, unsigned i){ asm { push bx mov bx, [bp+4] // BX = b mov bx[2], ax // ax polje pop WORD PTR [bx+4] // bx mov bx[6], cx // cx mov bx[8], dx // dx mov ax, bp[0] // AX = old_bp mov bx[12], ax // bp mov ax, bp[2] // AX = pc_ret mov bx[10], ax // pc mov [bx], sp // running->sp=SP //skida se sa steka i, b, PC, BP add WORD PTR[bx], 8 } return 0; Sadržaj steka (u odnosu na BP): +6 i +4 b +2 PC +0 BP -2 BX Neophodno je da _setjmp u ovoj realizaciji ima isti potpis kao i longjump. Ako _setjmp ne bi imala parametre kao i _longjmp, onda u _longjump ne bismo smeli da imamo liniju return i. Druga varijantna implementacije je data u fajlu vezbe1_zad1.cpp. Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Решење (2/3) Sadržaj steka (u odnosu na BP): +6 i +4 b +2 PC +0 BP unsigned _longjmp(cnt_buf *b, unsigned i){ asm { mov bx, [bp+4] // BX = b; mov ax, [bp+6] // AX = i; mov sp, [bx] // restauriramo stek push ax // Vracamo parametar i, push bx // b, push WORD PTR bx[10] // pc, push WORD PTR bx[12] // i bp na stek. mov bp, sp // BP <= SP mov ax, bx[2] // restauriramo AX, BX … push WORD PTR bx[4] // cuvamo bx polje na steku mov cx, bx[6] mov dx, bx[8] pop bx } return i; Чест случај је да компајлери генеришу такав код да вредност враћају у неком од регистара. За 8086 углавном важи да се вредност враћа у регистру АХ. Зато се ова линија преводи у: mov ax, [bp+6] pop BP ret Sadržaj Restauriranog Steka (potreban za povratak na setjmp): i b PC BP Primetiti da je bilo nepotrebno cuvati registar ax, kada ce _longjmp svakako da mu postavi vrednost “i” nakon restauracije. Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Решење (3/3) void createThread(PCB *newPCB, void (*body)()) { newPCB->stack = new unsigned[1024]; newPCB->context = new cnt_buf; newPCB->context->pc = FP_OFF(body); newPCB->context->sp = FP_OFF(newPCB->stack+1024); } Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Задатак 9 Написати корутину dispatch()коришћењем функције: void yield(unsigned* oldSP, unsigned* newSP); Прва половина функције чува контекст на текућем стеку и потом памти тренутну врeдност регистра SP у локацији на коју показује oldSP. Друга половина прво у регистар SP уписује садржај локације на коју показује newSP и потом са стека рестаурира контекст. yield() kada cuva kontekst to radi na steku (slicno kao u zadatku 4). Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Решење Проблем: Потребно је познавати имплементацију yield() f-je да би се креирао почетни контекст. struct PCB { unsigned SP; }; void dispatch() { unsigned *oldSP = &running->SP; Scheduler::put(running); running = Scheduler::get(); yield(oldSP, &running->SP); } Оперативни системи 1, ЕТФ 2017.

Оперативни системи 1, ЕТФ 2017. Задатак 10 Прокоментарисати претходне задатке уколико се dispatch() позива из прекидне рутине. Шта је у том случају проблем и како се решава? Оперативни системи 1, ЕТФ 2017.

Решењe На почетку се забрањује преузимање процесора. Чување контекста void dispatch() { lock() asm { // cuva registre sa podacima na steku push ax // sta bi se desilo da ne cuvamo AX? push bx push cx push dx mov bx, running mov [bx], sp // cuva registar sp } Scheduler::put(running); running = Scheduler::get(); asm { mov sp, [bx] // restauira registar sp pop dx // restauira registre sa podacima pop cx pop bx pop ax unlock() Чување контекста до сада извршаване нити Рестаурација контекста нити која се наставља Stigne se do nove dodele za running promenljivu, desi se prekid i ponovo se pozove dispatch odatle. Cuvaju se registri na steku, a tekuca vrednost sp registra se sacuva u pogresnoj pcb strukturi. На крају се поново дозвољава преузимање процесора. Оперативни системи 1, ЕТФ 2017.