Bufor kołowy - WEMiF
Bufor kołowy - WEMiF
Bufor kołowy - WEMiF
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 || | | | || | | |