01.05.2013 Views

Bufor kołowy - WEMiF

Bufor kołowy - WEMiF

Bufor kołowy - WEMiF

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

POLITECHNIKA WROCŁAWSKA<br />

WYDZIAŁ ELEKTRONIKI MIKROSYSTEMOW I FOTONIKI<br />

BUFOR KOŁOWY<br />

<strong>Bufor</strong> <strong>kołowy</strong> można porównać do tablicy danych która nie ma początku ani końca. Do<br />

pracy na takim buforze niezbędne są dwa wskaźniki. Pierwszy z nich pokazuje gdzie należy zapisać<br />

daną w buforze, drugi skąd odczytać. Po każdej operacji zapisu lub odczytu odpowiedni wskaźnik<br />

jest inkrementowany, aby pokazywać na następny element bufora (wskaźnik do zapisu pokazuje<br />

następny wolny element a wskaźnik do odczytu pierwszy nieodczytany element).<br />

Ponieważ nie dysponujemy nieskończenie wielką pamięcią, nasz bufor musi mieć<br />

skończony rozmiar. Aby była możliwość ciągłej pracy na takim buforze, projektuje się takie<br />

procedury, aby wskaźniki po napotkaniu końca tablicy zaczynały wskazywać na początek tablicy.<br />

Takie rozwiązanie pozwala zagospodarować nieużywaną pamięć, gdzie mieszczą się stare dane.<br />

Jednakże istnieje niebezpieczeństwo nadpisania jeszcze nie odebranych danych.<br />

Przedstawione powyżej schematy działania dotyczą bufora kołowego z dostępem FIFO<br />

(First Input – First Output). <strong>Bufor</strong> <strong>kołowy</strong> można również używać jako tablicę skończonej liczby<br />

elementów, której początek zmienia się w czasie. Takie zastosowanie jest wygodne gdy chcemy<br />

dopisywać kolejne próbki do tablicy i zarazem pamiętać stałą ilość starych próbek. Próbki które są<br />

już zbyt stare zostają nadpisane nowymi (są tracone).<br />

REALIZACJA BUFORA KOŁOWEGO<br />

Do pracy na takim buforze niezbędne są:<br />

● tablica o określonej długości N,<br />

● wskaźnik do zapisu danych,<br />

● wskaźnik do odczytu danych.<br />

Dla wygody korzystania z bufora warto stworzyć gotowe procedury do jego obsługi:<br />

● inicjacja wskaźników,<br />

● zapis danej<br />

● odczyt danej


Funkcja do inicjacji wskaźników ustawia wskaźniki odczytu i zapisu tak, aby wskazywały<br />

na początek bufora (wskaźniki pokazują na ten sam element). Jeżeli wskaźniki wskazują na ten sam<br />

element, to jest to informacja o tym że bufor jest pusty i nie ma w nim danych do odczytu.<br />

Funkcja zapisu danej do bufora zapisuje daną pod adres wskazywany przez wskaźnik<br />

zapisu, następnie wskaźnik ten jest inkrementowany tak, aby wskazywał kolejne miejsce do zapisu<br />

kolejnej danej. Jeżeli wskaźnik dojdzie do końca tablicy, to po kolejnym zapisie danej do bufora<br />

powinien on ustawić się na pierwszy element tablicy. Należy zwrócić uwagę na przypadek, w<br />

którym wskaźnik zapisu zbliża się z drugiej strony do wskaźnika odczytu. Jeżeli pozostało tylko<br />

jedno wolne pole między wskaźnikami i nastąpi zapis, to po inkrementacji wskaźniki zapisu i<br />

odczytu będą wskazywały na ten sam element. Aby odróżnić ten przypadek od przypadku, gdy<br />

bufor jest pusty, należy pozostawić jeden element odstępu między wskaźnikami, czyli wstrzymać<br />

zapis do czasu aż zwolni się miejsce w buforze.<br />

Funkcja odczytująca zwraca wartość, na którą wskazuje wskaźnik odczytu, a następnie<br />

inkrementuje go. Jeżeli wskaźnik odczytu jest na końcu tablicy to należy przy następnym odczycie<br />

przesunąć go na początek. Jeśli wskaźnik do odczytu wskazuje na ten sam element co wskaźnik do<br />

zapisu (wskaźniki są równe), oznacza to, że bufor jest pusty i należy zaniechać odczytu.<br />

Do pracy na buforze można wykorzystać wskaźnik tego samego typu co bufor:<br />

Int16 <strong>Bufor</strong>Kolowy[ Rozmiar ];<br />

Int16 *wskZapis;<br />

Int16 *wskOdczyt;<br />

Po każdej operacji inkrementacji należy sprawdzić, czy wskaźnik nie pokazuje poza obszar<br />

tablicy. Jeśli pokazuje, to należy go przesunąć na początek tablicy:<br />

...<br />

*wskZapis = DANA_WEJŚCIOWA;<br />

wskZapis ++;<br />

if( wskZapis >= <strong>Bufor</strong>Kolowy + Rozmiar ) wskZapis = <strong>Bufor</strong>Kolowy;<br />

...<br />

Takie podejście wymaga, aby za każdym razem wykonać skok warunkowy, co jest<br />

powiązane z przerywaniem potoku procesora. Inną metodą uzyskania podobnego efektu jest<br />

wykorzystanie reszty z dzielenia. To podejście nie wykonuje skoku warunkowego, więc nie<br />

przerywa potoku rozkazów procesora. Do realizacji takiego algorytmu potrzebujemy dodatkowej<br />

zmiennej, która będzie liczyła na którą pozycję skierowany jest wskaźnik:<br />

Uint32 WektorZapisu;<br />

Uint32 WektorZapisu;<br />

...<br />

<strong>Bufor</strong>Kolowy[WektorZapisu] = DANA_WEJŚCIOWA;<br />

WektorZapisu ++;<br />

WektorZapisu = WektorZapisu % Rozmiar;<br />

...<br />

Operacja dzielenia ma jednak swoje wady. Najważniejszą z naszego punktu widzenia jest jej<br />

czasochłonność. O ile operacja dodawania, odejmowania oraz inne operacje logiczne trwają jeden<br />

cykl, tak dzielenie jest sekwencyjne. Procesory sygnałowe zaopatrzone są w jednostkę mnożącą<br />

wykonującą operacje mnożenia również w jednym cyklu. Niestety odwrotność mnożenia nie trwa<br />

tak samo długo.<br />

Praca z systemami cyfrowymi wymaga od programisty pewnego przystosowania. Procesor<br />

pracuje na liczbach binarnym w kodzie dwójkowym. Ludzie posiadają dziesięć palców, zatem<br />

naturalny jest dla nas kod dziesiętny. Krążą historie, że kosmici posiadają 12 palców i od wieków<br />

nawiedzają planetę Ziemię czego śladem mają być szczątki systemu tuzinowego. Mnożenie liczby<br />

przez 10 w kodzie dziesiętnym przekłada się na przesunięcia przecinka dziesiętnego w lewo<br />

lub inkrementacją wykładnika w notacji naukowej. W przypadku dzielenia jest odwrotnie:<br />

przecinek jest przesuwany w prawo a wykładnik jest dekrementowany. Jeśli we wcześniej<br />

opisanych operacjach użyjemy potęgi liczby dziesięć, to operacje przesunięcia przecinka lub<br />

zmiany wykładnika zostaną wykonane tyle razy ile wynosiła potęga. Reszta z dzielenia przez 10<br />

jest tym co zostanie po przecinku w wyniku dzielenia. Takie same efekty powodują pomnożenie


oraz dzielenie liczby przez 2 w kodzie binarnym. Drugim bardzo ważnym narzędziem jest algebra<br />

Boole'a, czyli operacje na bitach. Do dyspozycji są operacje sumy logicznej, iloczynu logicznego,<br />

negacji bitowej oraz przesunięcia bitowego. Bardzo ważny jest jeszcze sposób interpretacji liczb w<br />

procesorze. Jeżeli posiadamy zmienną ośmiobitową, to możemy w niej przechować za pomocą<br />

naturalnego kodu dziesiętnego wartości od 0 do 255. W tej samej zmiennej za pomocą kodu z<br />

uzupełnieniem do dwóch (U2) można zakodować wartości od -128 do 127. Za każdym razem<br />

kodowanych jest 256 wartości. Liczba 256 jest potęgą dwójki!<br />

Przykład obliczeń w kodzie dziesiętnym<br />

1234 * 10 = 12340 mnożenie przez 10<br />

1234 * 10 5 = 123400000 mnożenie przez potęgę dziesiątki<br />

1234 : 100 = 12,34 = 12 + reszty 34 dzielenie przez potęgę dziesiątki<br />

Przykład obliczeń w kodzie binarnym<br />

1011 * 10 = 10110 mnożenie przez dwójkę<br />

1011 * 100000 = 101100000 mnożenie przez 32 (potęgę dwójki)<br />

1011 : 100 = 10,11 = 10 + reszty 10 dzielenie przez potęgę dwójki<br />

Sposoby interpretacji danych binarnych<br />

Numer kombinacji Postać binarna NKB U2<br />

1 0 0 0 0 0<br />

2 0 0 1 1 1<br />

3 0 1 0 2 2<br />

4 0 1 1 3 3<br />

5 1 0 0 4 -4<br />

6 1 0 1 5 -3<br />

7 1 1 0 6 -2<br />

8 1 1 1 7 -1<br />

Operacje możenia przez potęgę dwójki można wykonać w języku C za pomocą operatora<br />

przesunięcia bitowego w lewo:<br />

1101 * 100000 = 1101 > 2 = 11,01.<br />

Resztę z dzielenia przez potęgę dwójki można uzyskać poprzez operację maskowania, czyli z<br />

wykorzystaniem iloczynu logicznego:<br />

1101 % 100 = 1101 & (100 – 1) = 1101 & 0011 = 0001.<br />

Wzór ogólny na resztę z dzielenia przez potęgę dwójki można zapisać jako:<br />

A % B = A & (B – 1), gdzie B jest potęgą dwójki.<br />

Zakładając, że rozmiar tablicy danych będzie potęgą dwójki, w powyższym algorytmie adresowania<br />

tablicy danych można zastąpić dzielenie operacją iloczynu bitowego:<br />

...<br />

<strong>Bufor</strong>Kolowy[WektorZapisu] = DANA_WEJŚCIOWA;<br />

WektorZapisu ++;<br />

WektorZapisu = WektorZapisu & (Rozmiar -1);<br />

...<br />

Sprawdzanie warunku możliwości odczytu z bufora jest najprostszą operacją, gdyż wymaga


porównania ze sobą dwóch wskaźników lub wektorów.<br />

...<br />

if(wskOdczyt == wskZapis) return NULL; //pusty bufor<br />

else{ //skoro jest coś w buforze to trzeba to wysłać<br />

}<br />

...<br />

lub dla zapisu z wektorami:<br />

...<br />

if(WektorOdczytu == WektorZapisu) return NULL; //pusty bufor<br />

else{ //skoro jest coś w buforze to trzeba to wysłać<br />

}<br />

...<br />

Sprawdzenie warunku na wolne miejsce do zapisu danych może początkowo sprawić więcej<br />

trudności niż się to na pierwszy rzut oka wydaje. W większości przypadków należy sprawdzić czy<br />

wskaźnik zapisu wskazuje na to samo pole lub dalsze co wskaźnik odczytu (rys. 1), lub o co<br />

najmniej dwa pola przed polem na które wskazuje wskaźnik odczytu. Czyli interesuje nas różnica<br />

pól pomiędzy wskaźnikami, co za tym idzie różnica adresów.<br />

...<br />

if( (wskZapis >= wskOdczyt) || ((wskOdczyt – wskZapis) > 1) )<br />

{ //skoro jest miejsce to można zapisać<br />

}<br />

else return; //pełny bufor<br />

...<br />

lub dla zapisu z wektorami:<br />

...<br />

if( (WektorZapisu >=WektorOdczytu) ||<br />

(WektorOdczytu – WektorZapisu) > 1) )<br />

{ //skoro jest miejsce to można zapisać<br />

}<br />

else return; //pełny bufor<br />

...<br />

Jeszcze pozostaje kwestia rozpatrzenia dwóch przypadków kiedy wskaźnik odczytu znajduje<br />

się na zerowym i pierwszym miejscu a wskaźnik zapisu odpowiednio na przedostatnim i ostatnim.<br />

Uwzględnienie tych warunków jest niezbędne do prawidłowej pracy bufora i będzie dodatkowo<br />

rozbudowywało warunki, czyli zwiększało liczbę skoków warunkowych. Każdy skok warunkowy<br />

to przerwanie potoku procesora, czyli dłuższy czas realizacji kodu. Rozpatrzenie tych warunków<br />

pozostawimy czytelnikom.<br />

Innym sposobem sprawdzenia warunku możliwości zapisu do bufora kołowego jest<br />

skorzystanie z reszty z dzielenia. Aby wyeliminować przypadek, gdzie w wyniku odejmowania<br />

pojawia się wartość ujemna, do odjemnej w równaniu warunku dodajemy długość bufora. Aby<br />

wynik mieścił się w rozmiarze bufora, należy obliczyć resztę z dzielenia przez rozmiar bufora.<br />

Wyniki poniższych działań zwracają ilość wolnego miejsca w buforze:<br />

( (wskOdczyt + Rozmiar) – wskZapis ) % Rozmiar<br />

( (WektorOdczytu + Rozmiar) – WektorZapisu ) % Rozmiar<br />

Załóżmy że długość tablicy wynosi tysiąc elementów (10e3). W pierwszym przypadku,


załóżmy że WektorOdczytu wynosi 20 a WektorZapisu 900 (rys.1). W tej sytuacji wynikiem<br />

równania będzie:<br />

((20+1000)–900)%1000 = (1020-900)%1000 = 120%1000 = 120<br />

W drugim przypadku, załóżmy że WektorOdczytu wynosi 900 a WektorZapisu 20 (rys.<br />

2). W tej sytuacji wynikiem równania będzie:<br />

((900+1000)–20)%1000 = (1900-20)%1000 = 1880%1000 = 880<br />

Jeżeli założymy że rozmiar tablicy na której budujemy bufor <strong>kołowy</strong> będzie potęgą dwójki,<br />

to czasochłonną operację dzielenia można zastąpić iloczynem logicznym:<br />

( (wskOdczyt + Rozmiar) – wskZapis ) & (Rozmiar -1)<br />

( (WektorOdczytu + Rozmiar) – WektorZapisu ) & (Rozmiar -1)<br />

W tym miejscu należy przypomnieć sobie zasady kodowania liczb w kodzie U2. Należy<br />

skorzystać z wiadomości z zajęć Podstaw Techniki Cyfrowej i Mikroprocesorowej. Załóżmy, że<br />

pracujemy na zmiennych trzydziestodwubitowych a operacje arytmetyczne będą wykonywane<br />

zgodnie z kodowaniem U2. Podobnie jak w poprzednich przykładach, rozpatrzmy dwa przypadki.<br />

Rozmiar tablicy danych niech wynosi 1024. WektorOdczytu wynosi 20 a WektorZapisu 900<br />

(rys.1). Aby lepiej zrozumieć operacje arytmetyczne procesora, najlepiej jest przedstawić dane w<br />

formacie z jakim on pracuje, czyli w binarnym.<br />

Nazwa Format danych<br />

Dziesiętny Heksadecymalny Binarny<br />

Rozmiar 1024 0x0000||0400 0000|0000|0000|0000||0000|0100|0000|0000<br />

WektorOdczytu 20 0x0000||0014 0000|0000|0000|0000||0000|0000|0001|0100<br />

WektorZapisu 900 0x0000||0384 0000|0000|0000|0000||0000|0011|1000|0100<br />

Wykonajmy teraz krok po kroku powyższe równanie:<br />

temp01 = (WektorOdczytu + Rozmiar) = 20 + 1024 = 1044<br />

temp01 1044 0x0000||0414 0000|0000|0000|0000||0000|0100|0001|0100<br />

temp02 = ( temp01 ) - WektorZapisu = 1044 – 900 = 144<br />

temp02 144 0x0000||0090 0000|0000|0000|0000||0000|0000|1001|0000<br />

temp03 = (Rozmiar -1)= 1024 – 1 = 1023<br />

temp03 1023 0x0000||03ff 0000|0000|0000|0000||0000|0011|1111|1111<br />

temp04 = ( temp02 ) & ( temp03 ) = 144 & 1023 = 144<br />

temp04 144 0x0000||0090 0000|0000|0000|0000||0000|0000|1001|0000<br />

Zróbmy to samo dla przypadku gdy WektorOdczytu wynosi 900 a WektorZapisu 20<br />

(rys.2).<br />

Nazwa Format danych<br />

Dziesiętny Heksadecymalny Binarny<br />

Rozmiar 1024 0x0000||0400 0000|0000|0000|0000||0000|0100|0000|0000<br />

WektorOdczytu 900 0x0000||0384 0000|0000|0000|0000||0000|0011|1000|0100<br />

WektorZapisu 20 0x0000||0014 0000|0000|0000|0000||0000|0000|0001|0100<br />

temp01 = (WektorOdczytu + Rozmiar) = 900 + 1024 = 1924<br />

temp01 1924 0x0000||0784 0000|0000|0000|0000||0000|0111|1000|0100<br />

temp02 = ( temp01 ) - WektorZapisu = 1924 – 20 = 1904<br />

temp02 1904 0x0000||0770 0000|0000|0000|0000||0000|0111|0111|0000


temp03 = (Rozmiar -1)= 1024 – 1 = 1023<br />

temp03 1023 0x0000||03ff 0000|0000|0000|0000||0000|0011|1111|1111<br />

temp04 = ( temp02 ) & ( temp03 ) = 1904 & 1023 =<br />

temp04 880 0x0000||0370 0000|0000|0000|0000||0000|0011|0111|0000<br />

Z powyższego przykładu widzimy, że bity powyżej dziewiątego nie mają znaczenia, gdyż są<br />

zerowane w trakcie operacji maskowania ( iloczynu logicznego). Wykorzystując wiedzę na temat<br />

arytmetyki w kodzie U2 powyższy wzór do obliczania wolnego obszaru można uprościć do:<br />

( wskOdczyt – wskZapis ) & (Rozmiar -1)<br />

( WektorOdczytu– WektorZapisu ) & (Rozmiar -1)<br />

Wykorzystując poprzedni przykład, przeanalizujmy powyższy wzór. Rozpatrzmy najpierw<br />

drugi przypadek. Rozmiar tablicy danych niech wynoci 1024. WektorOdczytu wynosi 900 a<br />

WektorZapisu 20 (rys.2).<br />

Nazwa Format danych<br />

Dziesiętny Heksadecymalny Binarny<br />

Rozmiar 1024 0x0000||0400 0000|0000|0000|0000||0000|0100|0000|0000<br />

WektorOdczytu 900 0x0000||0014 0000|0000|0000|0000||0000|0000|0001|0100<br />

WektorZapisu 20 0x0000||0384 0000|0000|0000|0000||0000|0011|1000|0100<br />

temp01 = WektorOdczytu - WektorZapisu = 900 – 20 = 880<br />

temp01 880 0x0000||0370 0000|0000|0000|0000||0000|0011|0111|0000<br />

temp02 = (Rozmiar -1)= 1024 – 1 = 1023<br />

temp02 1023 0x0000||03ff 0000|0000|0000|0000||0000|0011|1111|1111<br />

temp03 = ( temp01 ) & ( temp02 ) = 880 & 1023 = 880<br />

temp03 880 0x0000||0370 0000|0000|0000|0000||0000|0011|0111|0000<br />

Zróbmy to samo dla pierwszego przypadku gdy WektorOdczytu wynosi 900 a<br />

WektorZapisu 20 (rys.1).<br />

Nazwa Format danych<br />

Dziesiętny Heksadecymalny Binarny<br />

Rozmiar 1024 0x0000||0400 0000|0000|0000|0000||0000|0100|0000|0000<br />

WektorOdczytu 20 0x0000||0014 0000|0000|0000|0000||0000|0011|1000|0100<br />

WektorZapisu 900 0x0000||0384 0000|0000|0000|0000||0000|0000|0001|0100<br />

temp01 = WektorOdczytu - WektorZapisu = 20 – 900 = -880<br />

temp01 *-880 *0xFFFF||FC90 1111|1111|1111|1111||1111|1100|1001|0000<br />

temp02 = (Rozmiar -1)= 1024 – 1 = 1023<br />

temp02 1023 0x0000||03ff 0000|0000|0000|0000||0000|0011|1111|1111<br />

temp03 = ( temp01 ) & ( temp02 ) = (-880) & 1023 = 144<br />

temp03 144 0x0000||0370 0000|0000|0000|0000||0000|0000|1001|0000<br />

Wartość -880 w kodzie U2 dla trzydziestodwu bitowych liczb jest kodowana jako<br />

0xFFFFFC90. Standardowy kalkulator w popularnym systemie operacyjnym Microsoft Windows<br />

XP pracuje na zmiennej sześćdziesięcioczterobitowej. Dla tej zmiennej wartość -880 jest kodowana<br />

jako 0xFFFFFFFFFFFFFC90. Kalkulator ten nie przetworzy liczby z formatu heksadecymalnego


na dziesiętny za pomocą kodu U2 tylko na za pomocą naturalnego kodu binarnego. Konwersja<br />

liczby 0xFFFFFC90 na kod dziesiętny da wynik 4294966416. Aby bezbłędnie przeanalizować<br />

powyższe operacje arytmetyczne warto skorzystać z dowolnego kompilatora i debuggera języka C<br />

lub C++ dla procesorów klasy x86.<br />

Aby użyć bufora kołowego jako tablicy o ruchomym początku (rys. 3) należy odwoływać<br />

się do N-tego elementu licząc od najnowszego pola. Zerowy element tablicy (najmłodszy) znajduje<br />

się przed elementem wskazywanym przez wskaźnik do zapisu:<br />

BUF[0] = TAB[WektorZapisu - 1];<br />

Dowolny element znajduje się na pozycji:<br />

BUF[n] = TAB[WektorZapisu – 1 - n];<br />

Należy jeszcze uwzględnić koniec bufora, tak aby można było bezbłędnie pracować na całej<br />

długości tablicy, aby móc odczytywać dane dla dalszych elementów bufora z końca zaalokowanej<br />

w pamięci tablicy.<br />

BUF[n] = TAB[ (WektorZapisu – 1 – n) & (Rozmiar-1)];<br />

Przetwarzanie sygnałów niejednokrotnie wiąże się z wykonywaniem obliczeń za pomocą<br />

operacji splotu. Operacja ta zostanie przypomniana w innym rozdziale. W trakcie jej realizacji<br />

przemnaża się i sumuje elementy dwóch macierzy, jednej od początku drugiej od końca. Aby<br />

numerować elementy tablicy wspak można skorzystać z następującego wyrażenia:<br />

BUF[(Rozmiar-1)-n] = TAB[ (WektorZapisu + n) & (Rozmiar-1)]<br />

Prosty program do ilustracji działania bufora kołowego został umieszczony na stronie<br />

przedmiotu.<br />

Producenci procesorów sygnałowych poszli jeszcze krok dalej z optymalizacją działania<br />

programów. Do realizacji bufora kołowego zostały zaimplementowane proste, ale bardzo skuteczne<br />

akceleratory sprzętowe. Podobnie jak nasze wcześniejsze optymalizacje, również i ta wymaga<br />

wykonania trudniejszej inicjacji po to, by można było potem dużo szybciej realizować algorytmy.<br />

Warto zauważyć pewne zależności. Realizacja sumatora wymaga dla każdego bitu dwóch<br />

bramek XOR, dwóch bramek AND oraz jednej bramki OR. Realizacja sumy logicznej wymaga<br />

jednej bramki OR.<br />

W procesorach sygnałowych znajdują się specjalne rejestry do relacji specjalnych trybów<br />

adresacji. W tym ćwiczeniu zostanie omówiona adresacja kołowa.<br />

Do realizacji sprzętowej adresacji kołowej wymagane są trzy rejestry. Pierwszy z nich<br />

przechowuje adres wskaźnika, za jego pomocą będzie realizowana adresacja wewnątrz bufora<br />

kołowego. Drugi zawiera wielkość obszaru pamięci przeznaczonej na bufor <strong>kołowy</strong>. Rozmiar<br />

tablicy musi być potęgą dwójki. Trzeci rejestr zawiera adres bazowy tablicy. Adres ten musi być<br />

podzielny przez rozmiar tablicy bez reszty. Do realizacji adresowania kołowego wykonane jest<br />

sprzętowo następujące równanie:<br />

AdresWPamięci = ( AdresWewnętrzny & (RozmiarTablicy – 1) ) | AdresBazowy<br />

Załóżmy, że rozmiar tablicy wynosi 256 a adres bazowy 0xC400. Adres wewnętrzny może<br />

przyjąć dowolną wielkość, ponieważ interpretowane będzie tylko modulo z niego. Sytuację tę<br />

obrazuje poniższy rysunek.


Zadania do samodzielnych obliczeń:<br />

Obliczyć ilość wolnego miejsca w buforze <strong>kołowy</strong>m korzystając z najbardziej optymalnego wzoru:<br />

Ćwiczenie nr 1:<br />

Nazwa Format danych<br />

Dziesiętny Heksadecymalny Binarny<br />

Rozmiar 1024 0x || | | | || | | |<br />

WektorOdczytu 800 0x || | | | || | | |<br />

WektorZapisu 40 0x || | | | || | | |<br />

temp01 = WektorOdczytu - WektorZapisu = – =<br />

temp01 0x || | | | || | | |<br />

temp02 = (Rozmiar -1)= – =<br />

temp02 0x || | | | || | | |<br />

temp03 = ( temp01 ) & ( temp02 ) = & =<br />

temp03 0x || | | | || | | |<br />

Ćwiczenie nr 2:<br />

Nazwa Format danych<br />

Dziesiętny Heksadecymalny Binarny<br />

Rozmiar 1024 0x || | | | || | | |<br />

WektorOdczytu 40 0x || | | | || | | |<br />

WektorZapisu 400 0x || | | | || | | |<br />

temp01 = WektorOdczytu - WektorZapisu = – =<br />

temp01 0x || | | | || | | |<br />

temp02 = (Rozmiar -1)= – =<br />

temp02 0x || | | | || | | |<br />

temp03 = ( temp01 ) & ( temp02 ) = & =<br />

temp03 0x || | | | || | | |<br />

Ćwiczenie nr 3:<br />

Nazwa Format danych<br />

Dziesiętny Heksadecymalny Binarny<br />

Rozmiar 1024 0x || | | | || | | |<br />

AdresOdczytu 0x0046|2349 | | | || | | |<br />

AdresZapisu 0x0046|2394 | | | || | | |


temp01 = AdresOdczytu - AdresZapisu = – =<br />

temp01 0x || | | | || | | |<br />

temp02 = (Rozmiar -1)= – =<br />

temp02 0x || | | | || | | |<br />

temp03 = ( temp01 ) & ( temp02 ) = & =<br />

temp03 0x || | | | || | | |<br />

Ćwiczenie nr 4:<br />

Nazwa Format danych<br />

Dziesiętny Heksadecymalny Binarny<br />

Rozmiar 1024 0x || | | | || | | |<br />

AdresOdczytu 0x0369|2394 | | | || | | |<br />

AdresZapisu 0x0369|2349 | | | || | | |<br />

temp01 = AdresOdczytu - AdresZapisu = – =<br />

temp01 0x || | | | || | | |<br />

temp02 = (Rozmiar -1)= – =<br />

temp02 0x || | | | || | | |<br />

temp03 = ( temp01 ) & ( temp02 ) = & =<br />

temp03 0x || | | | || | | |<br />

Ćwiczenie nr 5:<br />

Nazwa Format danych<br />

Dziesiętny Heksadecymalny Binarny<br />

Rozmiar 1024 0x || | | | || | | |<br />

AdresOdczytu 0x03CA|D3B4 | | | || | | |<br />

AdresZapisu 0x03CA|D39E | | | || | | |<br />

temp01 = AdresOdczytu - AdresZapisu = – =<br />

temp01 0x || | | | || | | |<br />

temp02 = (Rozmiar -1)= – =<br />

temp02 0x || | | | || | | |<br />

temp03 = ( temp01 ) & ( temp02 ) = & =<br />

temp03 0x || | | | || | | |


Ćwiczenie nr 6:<br />

Nazwa Format danych<br />

Dziesiętny Heksadecymalny Binarny<br />

Rozmiar 1024 0x || | | | || | | |<br />

AdresOdczytu 0x03CA|D39E | | | || | | |<br />

AdresZapisu 0x03CA|D3B4 | | | || | | |<br />

temp01 = AdresOdczytu - AdresZapisu = – =<br />

temp01 0x || | | | || | | |<br />

temp02 = (Rozmiar -1)= – =<br />

temp02 0x || | | | || | | |<br />

temp03 = ( temp01 ) & ( temp02 ) = & =<br />

temp03 0x || | | | || | | |<br />

Ćwiczenie nr 7 (szablon):<br />

Nazwa Format danych<br />

Dziesiętny Heksadecymalny Binarny<br />

Rozmiar 0x || | | | || | | |<br />

Adr/WektOdczytu 0x || | | | || | | |<br />

Adr/WektZapisu 0x || | | | || | | |<br />

temp01 = AdresOdczytu - AdresZapisu = – =<br />

temp01 0x || | | | || | | |<br />

temp02 = (Rozmiar -1)= – =<br />

temp02 0x || | | | || | | |<br />

temp03 = ( temp01 ) & ( temp02 ) = & =<br />

temp03 0x || | | | || | | |

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!