Digitaal rekenen
Wanneer U reeds op de hoogte bent van het decimale, hexadecimale en binaire talstelsel, van rekenen met binaire getallen, 2's complement notatie, BCD codes etc, dan kunt U dit gedeelte van de cursus snel doorlezen. Wanneer dit niet het geval is, neem dan de tijd om dit stuk aandachtig te lezen en te begrijpen. De theorie die hier wordt behandeld ligt ten grondslag aan de werking van de
micro-controller (en alle andere digitale computers....)
Getallen en talstels
Getallen geven hoeveelheden aan. Bij voorkeur moet de wijze waarop de hoeveelheden worden aangegeven zich lenen voor berekeningen hierop (optellen, aftrekken, vermenigvuldigen, delen, ...) Er zijn vele manieren om hoeveelheden aan te geven, maar niet alle manieren lenen zich goed voor het uitvoeren van de genoemde operaties. Zo kunt u de hoeveelheden één t/m tien bijvoorbeeld weergeven door de vingers aan Uw handen al dan niet op te steken. Of U kunt 'turven' op papier. U kunt ook denken aan de wijze waarop de Romeinen hoeveelheden aangaven (in zg. Romeinse cijfers, zoals op sommige klokken.)
Dat niet alle methoden even geschikt zijn om berekeningen eenvoudig mogelijk te maken blijkt wel wanneer U probeert MCMXXVI op te tellen bij CMIX. Voor deze opgave gesteld zult U waarschijnlijk eerst de getallen vanuit de Romeinse schrijfwijze vertalen naar de door ons gebruikte schrijfwijze, dan de optelling uitvoeren, en vervolgens het resultaat terugvertalen naar de Romeinse schrijfwijze. Dat de berekening in onze schrijfwijze zoveel eenvoudiger is, komt door de regelmaat en de structuur van de manier waarop de getallen gevormd worden in ons talstelsel.
Het decimale stelsel
In het dagelijks leven gebruiken wij het 'decimale' stelsel. Dit is een talstelsel met 'grondtal' tien. Elk decimaal getal is te schrijven als optelling van een aantal machten van tien. Zo kunnen we 1537 schrijven als:
1537 = 1 x 10^3 + 5 x 10^2 + 3 x 10^1 + 7 x 10^0
Er zijn tien symbolen (de cijfers '0' t/m '9') nodig voor de tien 'basis hoeveelheden' nul t/m negen. Alle grotere getallen kunnen worden samengesteld uit combinaties van deze symbolen (cijfers), waarbij een eigen waarde wordt toegekend aan de plaats van een cijfer in een getal (rechts de eenheden, links daarvan de tientallen, dan de honderdtallen, etc.)
De regelmaat van deze schrijfwijze heeft tot gevolg dat rekenen met getallen die op deze manier zijn weergegeven betrekkelijk eenvoudig is. De basisregels kunnen al onderwezen worden aan kinderen op de lagere school.
Dat wij het decimale stelsel gebruiken (met grondtal tien) wordt door de meesten verklaard door het feit dat we tien vingers hebben. In feite is de keuze voor het grondtal tien willekeurig. Zo kan op dezelfde manier en met evenveel gemak een talstelsel worden gebruikt met een ander grondtal. In de computertechniek zijn talstelsels met het grondtal twee,
acht en zestien populair.
Het binaire stelsel
Een talstelsel met grondtal twee (het binaire stelsel) heeft twee symbolen nodig voor de 'basishoeveelheden' nul en één. Het ligt voor de hand om hiervoor de symbolen '0', en '1' te kiezen. Hoeveelheden die groter zijn dan één, kunnen dan worden geschreven als combinaties van deze symbolen (cijfers), waarbij weer een eigen waarde wordt toegekend aan de plaats van een cijfer in een getal. Omdat dit stelsel het grondtal twee heeft, zijn de getallen opgebouwd uit machten van twee. Het binaire getal 110101 staat dan voor:
110101 = 1 x 2^5 + 1 x 2^4 + 0 x 2^3 + 1 x 2^2 + 0 x 2^1 + 1 x 2^0
Op de meest rechtse plaats staan de eenheden (2^0), links daarvan de 'tweetallen'
(2^1), dan de 'viertallen' (2^2), dan 'achttallen' (2^3), etc...
Het hexadecimale stelsel
Dezelfde regelmaat als in het decimale of binaire stelsel, is terug te vinden in het talstelsel met grondtal zestien (het hexadecimale stelsel.) Dit stelsel heeft zestien symbolen nodig voor de 'basishoeveelheden' nul t/m vijftien. Het ligt voor de hand om hiervoor de symbolen '0' t/m '9' te kiezen voor de eerste tien symbolen. De andere zes symbolen worden geleend van de letters: 'A', 'B', 'C', 'D', 'E' en 'F'. Hoeveelheden die groter zijn dan vijftien, kunnen dan worden geschreven als combinaties van deze symbolen, waarbij weer een eigen waarde wordt toegekend aan de plaats van het symbool in een getal. Omdat dit stelsel het grondtal zestien heeft, zijn de getallen opgebouwd uit machten van zestien. Het hexadecimale getal 643A staat dan voor:
643A = 6 x 16^3 + 4 x 16^2 + 3 x 16^1 + A x 16^0
Samenvattend zijn de symbolen uit de verschillende stelsels:
|
binair |
decimaal |
hexadecimaal |
betekenis |
|
|
|
0 |
0 |
0 |
nul |
|
1 |
1 |
1 |
één |
|
. |
2 |
2 |
twee |
|
.... |
.... |
.... |
..... |
|
. |
9 |
9 |
negen |
|
. |
. |
A |
tien |
|
. |
. |
B |
elf |
|
. |
. |
C |
twaalf |
|
. |
. |
D |
dertien |
|
. |
. |
E |
veertien |
|
. |
. |
F |
vijftien |
Onderstaand volgt een kleine tabel waarin geteld wordt volgens de besproken talstelsels:
|
decimaal |
hexadecimaal |
binair |
|
|
|
0 |
0 |
0000 |
|
1 |
1 |
0001 |
|
2 |
2 |
0010 |
|
3 |
3 |
0011 |
|
4 |
4 |
0100 |
|
5 |
5 |
0101 |
|
6 |
6 |
0110 |
|
7 |
7 |
0111 |
|
8 |
8 |
1000 |
|
9 |
9 |
1001 |
|
10 |
A |
1010 |
|
11 |
B |
1011 |
|
12 |
C |
1100 |
|
13 |
D |
1101 |
|
14 |
E |
1110 |
|
15 |
F |
1111 |
Wanneer we een getal zien, en niet weten in welk talstelsel dit getal is weergegeven, is het niet zonder meer duidelijk welke hoeveelheid precies bedoeld wordt. Om vergissingen te voorkomen zullen:
-
getallen in het binaire stelsel worden voorafgegaan door '%'
-
getallen in het hexadecimale stelsel worden voorafgegaan door '$'
-
getallen in het decimale stelsel gewoon worden weergegeven
Dus de hoeveelheid 'veertien' kan worden geschreven als 14 of $0E of %1110.
Waarom binair en hexadecimaal?
Computers werken met digitale schakelingen. De uitgang van zo'n schakeling kan twee toestanden aannemen ( '0', of '1'). Zo'n uitgang kan dus worden beschouwd als één cijfer van een binair getal. Een cijfer uit het binaire getal heet een 'bit' (een samenvoeging van 'BInary digiT', ofwel 'binair cijfer'.) Digitale computers werken in het binaire talstelsel.
Binaire getallen zijn voor mensen lastig te lezen. De lange rij enen en nullen waaruit een binair getal is opgebouwd werkt vergissingen en leesfouten in de hand.
In de bovenstaande tabel is al te zien, dat er precies vier bits nodig zijn om alle zestien basishoeveelheden uit het hexadecimale stelsel weer te kunnen geven. Een setje van vier bits komt precies overeen met één cijfer uit het hexadecimale stelsel. Dat betekent dat binaire getallen heel eenvoudig kunnen worden omgezet naar de hexadecimale schrijfwijze. En andersom. Hexadecimale getallen zijn een stuk compacter, en eenvoudiger leesbaar. In de computertechniek wordt daarom veel gebruik gemaakt van hexadecimale getallen.
Omzettingen tussen talstelsels.
Binair naar hexadecimaal
Omzetten van binair naar hexadecimaal gebeurt door het binaire getal op te knippen in stukjes van 4 bits (rechts beginnen.) Een groepje van 4 bits wordt ook wel een 'nibble' genoemd. Het bij elk nibble behorende hexadecimale cijfer wordt in de bovenstaande tabel gevonden.
Zo wordt:
%01101011 = $6B (0110 -> 6, en 1011 -> B )
Hexadecimaal naar binair
Omzetten van hexadecimaal naar binair gebeurt door voor elk van de hexadecimale cijfers het bijbehorende nibble uit de bovenstaande tabel te lezen en op te schrijven.
Zo wordt:
$F3 = %11110011 (F -> 1111, en 3 -> 0011 )
Het heeft zin Uzelf vertrouwd te maken met de tabel, zodat dit soort omzettingen voor U kinderspel wordt.
Binair en hexadecimaal naar decimaal
Uit de wijze waarop de getallen zijn opgebouwd (de plaats van een cijfer bepaalt de 'waarde' van dat cijfer) kunt U de waarde van een binair of hexadecimaal getal berekenen.
Zo is:
%110101 = 1 x 2^5 + 1 x 2^4 + 0 x 2^3 + 1 x 2^2 + 0 x 2^1 + 1 x 2^0
= 1 x 32 + 1 x 16 + 0 x 8 + 1 x 4 + 0 x 2 + 1 x 1 = 53
en
$643A = 6 x 16^3 + 4 x 16^2 + 3 x 16^1 + A x 16^0
= 6 x 4096 + 4 x 256 + 3 x 16 + 10 x 1 = 25658
Met een rekenmachine is dit eenvoudig te doen.
U kunt ook een tabel gebruiken. In de volgende tabel staan de decimale waarden van de hexadecimale cijfers, afhankelijk van de plaats die het cijfer in het getal heeft. De tabel is bruikbaar voor getallen van maximaal 4 cijfers (16-bits getallen.) U kunt deze tabel gebruiken om snel een getal van hexadecimaal naar decimaal om te zetten.
cijfer waarde
|
0 |
0 |
0 |
0 |
0 |
|
1 |
4096 |
256 |
16 |
1 |
|
2 |
8192 |
512 |
32 |
2 |
|
3 |
12288 |
768 |
48 |
3 |
|
4 |
16384 |
1024 |
64 |
4 |
|
5 |
20480 |
1280 |
80 |
5 |
|
6 |
24576 |
1536 |
96 |
6 |
|
7 |
28672 |
1792 |
112 |
7 |
|
8 |
32768 |
2048 |
128 |
8 |
|
9 |
36864 |
2304 |
144 |
9 |
|
A |
40960 |
2560 |
160 |
10 |
|
B |
45056 |
2816 |
176 |
11 |
|
C |
49152 |
3072 |
192 |
12 |
|
D |
53248 |
3328 |
208 |
13 |
|
E |
57344 |
3584 |
224 |
14 |
|
F |
61440 |
3840 |
240 |
15 |
Voorbeeld: Zet $A467 om naar decimaal.
-
Zoek in de meest rechtse kolom de waarde van '7' op : 7
-
Zoek in de kolom links daarvan de waarde van '6' op : 96
-
Zoek in de kolom links daarvan de waarde van '4' op : 1024
-
Zoek in de kolom links daarvan de waarde van 'A' op : 40960
-
Tel de gevonden waarden op : 42087
Decimaal naar binair of hexadecimaal
Om een decimaal getal om te zetten naar een getal in een ander stelsel moet U wat rekenwerk verrichten. Het is U vast op de lagere school al eens opgevallen dat getallen (in het decimale stelsel) zich heel eenvoudig laten delen door tien, of vermenigvuldigen met tien.
Vermenigvuldigen doet U simpelweg door een '0' achter het getal te plaatsen. Nu U beter weet hoe de getallen zijn opgebouwd, is dat ook goed te verklaren. Door een '0' achter het getal te plaatsen, schuiven alle andere cijfers één plaats naar links, en krijgen dus allemaal een hogere 'waarde' (tienmaal zo hoog.) Daardoor wordt het getal tienmaal zo groot. Voor getallen in het binaire of hexadecimale stelsel geldt natuurlijk precies hetzelfde. Zo kunt U een binair getal eenvoudig met twee vermenigvuldigen door een '0' achter het getal te plaatsen. En een hexadecimaal getal wordt met zestien vermenigvuldigd wanneer er een '0' achter gezet wordt.
Even eenvoudig is delen door tien (in het decimale stelsel.) U schuift alle cijfers één plaats naar rechts. Het meest rechtse cijfer van het oorspronkelijke getal vormt de 'rest' die U heeft (we werken uitsluitend met gehele getallen.) In het binaire stelsel deelt U door twee wanneer U alle cijfers één plaats naar rechts schuift. Ook hier houdt U het meest rechtse cijfer van het oorspronkelijke getal als 'rest' over. In het hexadecimale stelsel is het verhaal niet anders: hier deelt U door zestien door naar rechts te schuiven, het meest rechtse cijfer van het oorspronkelijke getal vormt de 'rest'.
Van het bovenstaande effect kunnen we gebruik maken wanneer een getal vanuit het decimale stelsel naar een ander stelsel omgezet moet worden. Om een getal in het decimale stelsel om te zetten naar het binaire stelsel gaat U dan als volgt te werk:
-
U deelt het decimale getal door 2. U noteert de 'rest' als binair cijfer (de 'rest' is altijd kleiner dan 2.)
-
U gebruikt de uitkomst van de vorige deling, en deelt opnieuw door 2. De 'rest' noteert U weer.
-
Zo gaat U door totdat de uitkomst van de deling 0 is (eventueel wel met een 'rest', die U uiteraard moet noteren
!)
-
Het binaire getal krijgt U door de gevonden 'resten' van rechts naar links op te schrijven.
Een voorbeeld:
53 / 2 = 26, rest 1 --> 1
26 / 2 = 13, rest 0 --> 01
13 / 2 = 6, rest 1 --> 101
6 / 2 = 3, rest 0 --> 0101
3 / 2 = 1, rest 1 --> 10101
1 / 2 = 0, rest 1 -->110101
De binaire schrijfwijze van 53 is dus %110101.
Om een getal vanuit het decimale stelsel om te zetten naar het hexadecimale stelsel gaat U als volgt te werk:
-
U deelt het decimale getal door 16. U noteert de 'rest' als hexadecimaal cijfer (de 'rest' is altijd kleiner dan 16.)
-
U gebruikt de uitkomst van de vorige deling, en deelt opnieuw door 16. De 'rest' noteert U weer.
-
Zo gaat U door totdat de uitkomst van de deling 0 is (eventueel wel met een 'rest', die U uiteraard moet noteren
!)
-
Het hexadecimale getal krijgt U door de gevonden 'resten' van rechts naar links op te schrijven.
Een voorbeeld:
25658 / 16 = 1603, rest 10 --> A
1603 / 16 = 100, rest 3 --> 3A
100 / 16 = 6, rest 4 --> 43A
6 / 16 = 0, rest 6 --> 643A
De hexadecimale schrijfwijze van 25658 is dus $643A.
Omdat delen door twee zoveel eenvoudiger is dan delen door zestien, is het meestal handiger een getal eerst om te zetten naar binair. Daarna kunt U het binaire getal met behulp van de tabel omzetten naar hexadecimaal.
Om snel 8-bits getallen om te zetten naar decimaal en vice-versa, kunt U ook de volgende tabel gebruiken:
|
|
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
A |
B |
C |
D |
E |
F |
|
|
|
0 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
|
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
|
2 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
|
3 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
|
4 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
|
5 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
|
6 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
|
7 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
|
8 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
|
9 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
|
A |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
|
B |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
|
C |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
|
D |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
|
E |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
|
F |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
U zoekt het decimale getal op in de tabel. Het 8-bits resultaat vormt U uit twee hexadecimale cijfers die U in de tabel kunt vinden. Het linker cijfer staat op de vertikale as, het rechter cijfer op de horizontale as.
De binaire representatie van het hexadecimal getal is te vinden met behulp van de tabel die eerder werd gegeven.
Optellen
Het decimale, hexadecimale en binaire stelsel hebben weliswaar een ander grondtal, maar de getallen zijn volgens dezelfde regels opgebouwd. De regels voor optellen en aftrekken zijn in het binaire of hexadecimale stelsel dan ook niet anders dan de regels die voor het decimale stelsel gelden.
Wanneer U twee decimale getallen optelt, begint U ermee de getallen recht onder elkaar te schrijven. Als de getallen niet evenlang zijn, vult U (waarschijnlijk alleen in gedachten) het kortste getal aan de linkerkant aan met nullen. Daarna telt U cijfer voor cijfer bij elkaar op. Is de som van twee cijfers groter dan negen, dan heeft U een 'carry' (in lagere-school taal: 'ééntje onthouden') die bij het volgende paar cijfers wordt opgeteld.
Wanneer de getallen in het binaire stelsel zijn gegeven, volgt U exact dezelfde procedure. Met als enig verschil dat de 'carry' nu ontstaat wanneer de som van twee cijfers groter is dan één.
Een voorbeeld:
|
%10001011 |
( 139 ) |
|
%00101110 |
( 46 ) |
|
--------------+ |
|
|
%10111001 |
( 185 ) |
Aan de rechterkant beginnend:
1 + 0 -> 1 (geen carry)
1 + 1 -> 2 (in binair 10, dus 0 opschrijven, carry = 1)
0 + 1 + 1 (carry) -> 2 (in binair 10, dus 0 opschrijven, carry = 1)
1 + 1 + 1 (carry) -> 3 (in binair 11, dus 1 opschrijven, carry = 1)
0 + 0 + 1 (carry) -> 1 (geen carry)
0 + 1 -> 1 (geen carry)
0 + 0 -> 0 (geen carry)
1 + 0 -> 1 (geen carry)
Wanneer de getallen in het hexadecimale stelsel zijn gegeven, volgt U ook dezelfde procedure. Met als enig verschil dat de 'carry' nu ontstaat wanneer de som van twee cijfers groter is dan vijftien.
Een voorbeeld:
|
$8B |
( 139 ) |
|
$2E |
( 46 ) |
|
---- + |
|
|
$B9 |
( 185 ) |
Aan de rechterkant beginnend:
$B + $E (11 + 14) -> 25 (in hex $19, dus 9 opschrijven, carry = 1)
$8 + $2 + 1 (carry) -> 11 (in hex $0B, dus B opschrijven, carry = 0)
Aftrekken
Wanneer U twee decimale getallen van elkaar aftrekt, begint U weer met de getallen recht onder elkaar te schrijven. Als de getallen niet evenlang zijn, vult U (waarschijnlijk alleen in gedachten) het kortste getal aan de linkerkant aan met nullen. Daarna trekt U cijfer voor cijfer van elkaar af. Is het cijfer dat U af moet trekken groter dan het cijfer waarvan het afgetrokken moet worden, dan komt U tekort. U 'leent' dan een eenheid van het cijfer meteen links. Deze heeft een tienmaal zo grote waarde, zodat dit lenen U tien eenheden oplevert. Dit lenen heet een 'borrow' (in lagere-school taal: 'ééntje lenen'.)
Wanneer de getallen in het binaire stelsel zijn gegeven, volgt U exact dezelfde procedure. Met als enig verschil dat de 'borrow' nu geen tien, maar twee eenheden oplevert.
Een voorbeeld:
|
%10001011 |
( 139 ) |
|
%00101110 |
( 46 ) |
|
-------------- |
|
%01011101 |
( 93 ) |
Aan de rechterkant beginnend:
1 - 0 -> 1 (geen borrow)
1 - 1 -> 0 (geen borrow)
0 - 1 -> -1 (een borrow levert twee eenheden op die erbij geteld mogen worden, dus 1 opschrijven, borrow = 1)
1 - 1 - 1 (borrow) -> -1 (een borrow levert twee eenheden op die erbij geteld mogen worden, dus 1 opschrijven, borrow = 1)
0 - 0 - 1 (borrow) -> -1 (een borrow levert twee eenheden op die erbij geteld mogen worden, dus 1 opschrijven, borrow = 1)
0 - 1 - 1 (borrow) -> -2 (een borrow levert twee eenheden op die erbij geteld mogen worden, dus 0 opschrijven, borrow = 1)
0 - 0 - 1 (borrow) -> -1 (een borrow levert twee eenheden op die erbij geteld mogen worden, dus 1 opschrijven, borrow = 1)
1 - 0 - 1 (borrow) -> 0
Wanneer de getallen in het hexadecimale stelsel zijn gegeven, volgt U ook dezelfde procedure. Met als enig verschil dat de 'borrow' nu zestien eenheden oplevert.
Een voorbeeld:
|
$8B |
( 139 ) |
|
$2E |
( 46 ) |
|
----- |
|
$5D |
( 93 ) |
Aan de rechterkant beginnend:
$B - $E (11 - 14) -> -3 (een borrow levert 16 eenheden op die erbij geteld mogen worden, dus 13 ($D) opschrijven, borrow = 1)
$8 - $2 - 1 (borrow) -> 5
Vermenigvuldigen
Het vermenigvuldigen van twee getallen uit het binaire stelsel gaat in grote lijnen hetzelfde als wanneer twee decimale getallen vermenigvuldigd worden. Dit komt weer omdat weliswaar het grondtal anders is, maar de rekenregels in principe hetzelfde zijn.
Uit de schrijfwijze van de getallen kan worden afgeleid wat er gedaan moet worden om het resultaat van een vermenigvuldiging te berekenen. Stel dat %1011 (11) vermenigvuldigd moet worden met %0110 (6.) U weet inmiddels, dat
%0110 = 0 x 2^3 + 1 x 2^2 + 1 x 2^1 + 0 x 2^0
%1011 x %0110 betekent derhalve:
%1011 x 0 x 2^3
+ %1011 x 1 x 2^2
+ %1011 x 1 x 2^1
+ %1011 x 0 x 2^0
Vermenigvuldigen met 2x betekent (in het binaire stelsel) 'x' plaatsen naar links schuiven (rechts aanvullen met nullen.) Voor een computer is schuiven natuurlijk erg gemakkelijk. Vermenigvuldigen komt neer op herhaald schuiven en optellen. Zo wordt %1011 x %0110 :
|
%1011 |
x |
0 |
x |
2^3 |
= |
0 |
x |
%1011000 |
= |
%0 |
|
%1011 |
x |
1 |
x |
2^2 |
= |
1 |
x |
%101100 |
= |
%101100 |
|
%1011 |
x |
1 |
x |
2^1 |
= |
1 |
x |
%10110 |
= |
%10110 |
|
%1011 |
x |
0 |
x |
2^0 |
= |
0 |
x |
%1011 |
= |
%0 |
|
+ |
%1000010 |
Wanneer een 'n'-bits getal wordt vermenigvuldigd met een 'm'-bits getal, moet voor het resultaat 'n+m' bits gereserveerd worden. Dus als twee 4-bits getallen vermenigvuldigd worden, levert dit maximaal een 8-bits resultaat op. Als U twee bytes vermenigvuldigd, past het resultaat in 16 bits.
Het algorithme ('recept') om twee binaire getallen N en M (van 'n' en 'm' bits) te vermenigvuldigen is:
-
reserveer (n+m) bits voor het resultaat R
-
R := 0
-
zolang N niet 0 is, doe dan:
-
Als het meest rechtse bit van N een '1' is, dan
R := R + M
-
N := N / 2 (naar rechts schuiven; het meest rechtse bit schuift 'er uit')
-
M := M x 2 (naar links schuiven)
De 68HC11 kent een instructie waarmee in één keer twee 8-bits getallen tot een 16-bits resultaat vermenigvuldigd kunnen worden. Hoe U met behulp van deze instructie ook grotere getallen kunt vermenigvuldigen wordt in een voorbeeld in een volgende les behandeld.
Delen
Om te zien hoe twee getallen in het binaire stelsel op elkaar gedeeld moeten worden, kijken we eerst weer naar de betekenis van de getallen.
Stel dat %1111 (15) gedeeld moet worden door %0101 (5). We weten dat bij een deling het resultaat maximaal hetzelfde aantal bits kan hebben als het getal dat gedeeld wordt (want als er door 1 gedeeld wordt is het resultaat gelijk aan het getal dat gedeeld wordt.) Noem dit resultaat X. X is in het voorbeeld een getal van 4 bits. We kunnen X weer schrijven als
X = X3 x 2^3 + X2 x 2^2 + X1 x 2^1 + X0 x 2^0
X3, X2, X1 en X0 zijn de bits waaruit het getal is opgebouwd. X3 t/m X0 zijn dus '0' of '1' (dat weten we nog niet.)
Er moet nu gelden:
X x %0101 = %1111 (want %1111 / %0101 moet X opleveren.)
Anders geschreven:
|
%0101 |
|
x |
X3 |
x |
2^3 |
|
+%0101 |
|
x |
X2 |
x |
2^2 |
|
+%0101 |
|
x |
X1 |
x |
2^1 |
|
+%0101 |
|
x |
X0 |
x |
2^0 |
|
---------+ |
|
|
=%1111 |
Ofwel:
|
|
%0101000 |
x |
X3 |
|
+ |
%0010100 |
x |
X2 |
|
+ |
%0001010 |
x |
X1 |
|
+ |
%0000101 |
x |
X0 |
|
|
--------------+ |
|
= |
%0001111 |
De som, %00001111 is blijkbaar opgebouwd uit 4 componenten:
%0101000 x X3, %0010100 x X2, %0001010 x X1, en %0000101 x X0,
die elk wèl (Xn = '1'), of nìet ( Xn = '0') aanwezig zijn.
We kunnen nu, bit-voor-bit, testen of X3, X2, X1 en X0 een '0' of een '1' moeten zijn.
Als X3 een '1' is, moet %0101000 in %0001111 'zitten'. Aangezien %0001111 kleiner is dan %0101000, kan X3 geen '1' zijn. Derhalve is X3 = 0.
Als X2 een '1' is, moet %0010100 in %0001111 'zitten'. Aangezien %0001111 kleiner is dan %0010100, kan X2 geen '1' zijn. Derhalve is X2 =
0
Als X1 een '1' is, moet %0001010 in %0001111 'zitten'. Aangezien %0001111 groter of gelijk is aan %0001010, is X1 een '1'. We moeten nu de component %0001010 van de som aftrekken, en verder testen met %0001111 - %0001010 = %0000101.
Als X0 een '1' is, moet %0000101 in %0000101 'zitten'. Aangezien %0000101 groter of gelijk is aan %0000101, is X0 een '1'. We moeten nu de component %0000101 van de som aftrekken, en verder testen met %0000101 - %0000101 = %0000000.
Nu alle bits getest zijn, is het resultaat X = %0011. Het getal waar op getest wordt is aan het eind van de berekening 0 geworden, zodat in dit geval geen 'rest' overblijft.
De 68HC11kent een instructie waarmee in één keer twee 16-bits getallen op elkaar gedeeld kunnen worden. Hoe U delingen op grotere getallen kunt programmeren wordt in een voorbeeld in een volgende les behandeld.
Negatieve getallen
In onze schrijfwijze worden negatieve getallen voorafgegaan door een min-teken. Wanneer we nu twee getallen optellen, en één van de twee is negatief, dan weten we dat we dit getal eigenlijk van het andere getal moeten aftrekken. En wanneer een negatief getal van een ander getal moet worden afgetrokken weten we, dat het er eigenlijk bij moet worden opgeteld. Voor een computer is het lastig een dergelijk onderscheid te maken tussen negatieve en positieve getallen. Immers, de bewerking die moet worden uitgevoerd (optellen of aftrekken) kan veranderen, afhankelijk van het teken van de getallen. Er is daarom een andere wijze gekozen om in de
microcomputer negatieve getallen te behandelen.
De computer werkt met getallen van een vast aantal cijfers (in het binaire stelsel: bits.) Gebruikelijk is bijvoorbeeld getallen van 8 bits (een byte), maar ook 16 bits (en meer) komt voor. Laten we eens zien wat er gebeurt wanneer we de bovenbeschreven regels volgen voor het aftrekken van twee binaire getallen, niet meer dan 8 bits gebruiken, en ervoor zorgen dat het resultaat negatief is.
Bijvoorbeeld:
|
%00101110 |
( 46 ) |
|
%01101110 |
( 110 ) |
|
---------- |
|
%11000000 |
( -64 ) |
Er is een 'borrow' vanuit het meest linkse bit, maar omdat er niet meer dan 8 bits gebruikt worden is deze borrow niet zichtbaar (de CPU onthoudt deze 'borrow' wel in een speciaal register.)
Uit het bovenstaand resultaat komt naar voren dat het getal -64 blijkbaar als %11000000 kan worden geschreven. We kunnen controleren of dit klopt, door bij %11000000 weer 64 op te tellen. De som moet dan uiteraard 0 zijn:
|
%11000000 |
( -64 ) |
|
%01000000 |
( 64 ) |
|
--------- + |
|
%00000000 |
( 0 ) |
Er is nu een 'carry' vanuit het meest linkse bit, maar ook deze is niet zichtbaar omdat er niet meer dan 8 bits gebruikt worden.
In de bovenstaande berekeningen zijn de standaard regels voor het optellen en aftrekken van binaire getallen gebruikt. De micro-controller hoeft dus niet te weten of een getal positief is of negatief, maar kan altijd dezelfde bewerking uitvoeren. U bepaalt zelf of U met getallen wilt werken die zowel positief- als negatief kunnen zijn, of met getallen die alleen positief kunnen zijn.
De notatie die op deze manier voor negatieve getallen ontstaat, heet de 'two's-complement' notatie (2's-complement.)
Een negatief getal heeft in deze notatie het meest significante bit (het meest linkse bit) op '1'.
Een getal wordt van teken veranderd door:
-
alle bits van het getal te inverteren (elke nul wordt een één, elke één wordt een nul.)
-
bij het resultaat 1 op te tellen.
Bijvoorbeeld:
5 = %00000101
alle bits inverteren en er 1 bij optellen:
%11111010
%00000001
---------+
%11111011 = -5
Ter controle kunnen we de op deze manier gevonden representatie van -5 weer bij 5 optellen. Het resultaat moet dan uiteraard 0 zijn:
%00000101 ( 5)
%11111011 ( -5)
--------- +
%00000000 ( 0)
Getallen zonder teken
Wanneer U met getallen zonder teken werkt (wanneer U bijvoorbeeld een byte gebruikt om pulsen op een I/O pin te tellen, weet U dat dit altijd een positief aantal moet zijn), dan kan in één byte geteld worden tot 255. Er kan in één byte 28 (256) verschillende getallen worden opgeborgen, van 0 t/m 255.
Wanneer een getal geen teken heeft (dus altijd een positief getal is), dan noemt men dit getal 'unsigned' (zonder teken.)
Getallen met teken
Wanneer U met getallen mèt teken wilt werken (U wilt bijvoorbeeld 8 - 17 uit kunnen rekenen), dan moet een deel van de 256 verschillende bitcombinaties die in een byte passen, worden gereserveerd voor de negatieve getallen. Er zijn 128 positieve getallen (van 0 t/m 127), en 128 negatieve getallen (van -1 t/m -128.)
Wanneer een getal zowel positief als negatief kan zijn, noemt men dit getal 'signed' (met teken.)
De micro-controller maakt geen onderscheid tussen 'signed' en 'unsigned' getallen. De instructie 'optellen' zal altijd tot dezelfde bewerking op de getallen leiden. Het hangt helemaal af van de betekenis van de getallen of U in het programma de getallen als 'signed' of 'unsigned' moet gebruiken. De
microcomputer kan alleen rekenen; van de betekenis van de getallen heeft alleen de programmeur weet.
De BCD code
Een andere manier om getallen in een computer weer te geven is de BCD code. BCD staat voor 'Binairy Coded Decimal', ofwel 'binair gecodeerde decimale' getallen. Bij deze code wordt voor elk van de tien cijfers uit het decimale stelsel een bitcode afgesproken. Voor de tien cijfers zijn tien codes nodig, waardoor elk cijfer 4 bits gebruikt.
De BCD code is:
|
cijfer |
BCD code |
|
0 |
0000 |
|
1 |
0001 |
|
2 |
0010 |
|
3 |
0011 |
|
4 |
0100 |
|
5 |
0101 |
|
6 |
0110 |
|
7 |
0111 |
|
8 |
1000 |
|
9 |
1001 |
Het decimale getal 1635 kan in BCD gecodeerd worden als:
1635 = 0001 0110 0011 0101 (BCD)
Omdat elk van de cijfers uit een getal direct gerepresenteerd wordt door een vier-bits code, is het zeer eenvoudig om getallen uit het decimale stelsel om te zetten naar BCD en andersom. De BCD code wordt dan ook vaak gebruikt als tussenstap wanneer getallen door de micro-computer zichtbaar gemaakt moeten worden (bijvoorbeeld op een display.) De
microcomputer heeft een instructie die het mogelijk maakt met BCD gecodeerde getallen te rekenen. Voor het werken met binaire getallen zijn veel meer instructies aanwezig, daarom wordt de BCD code meestal alleen als tussenstap gebruikt bij conversie van een binair getal naar een decimaal getal (voor op een display bijvoorbeeld.)
Andere codes
In een computer moeten, naast getallen, ook teksten verwerkt kunnen worden. Dit betekent dat er een code voor alle letters en leestekens uit het alfabet moet zijn. Hiervoor bestaat een standaard codering, de ASCII code (ASCII staat voor 'American Standard Code for Information Interchange'.)
De ASCII code geeft voor alle letters, cijfers en leestekens (en voor een aantal speciale tekens die gebruikt worden bij data-communicatie) een 7-bits code, volgens de volgende tabel:
|
|
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
|
0 |
NUL |
DLE |
SP |
0 |
@ |
P |
` |
p |
|
1 |
SOH |
DC1 |
! |
1 |
A |
Q |
a |
q |
|
2 |
STX |
DC2 |
" |
2 |
B |
R |
b |
r |
|
3 |
ETX |
DC3 |
# |
3 |
C |
S |
c |
s |
|
4 |
EOT |
DC4 |
$ |
4 |
D |
T |
d |
t |
|
5 |
ENQ |
NAK |
% |
5 |
E |
U |
e |
u |
|
6 |
ACK |
SYN |
& |
6 |
F |
V |
f |
v |
|
7 |
BEL |
ETB |
' |
7 |
G |
W |
g |
w |
|
8 |
BS |
CAN |
( |
8 |
H |
X |
h |
x |
|
9 |
HT |
EM |
) |
9 |
I |
Y |
i |
y |
|
A |
LF |
SUB |
* |
: |
J |
Z |
j |
z |
|
B |
VT |
ESC |
+ |
; |
K |
[ |
k |
{ |
|
C |
FF |
FS |
, |
< |
L |
\ |
l |
| |
|
D |
CR |
GS |
- |
= |
M |
] |
m |
} |
|
E |
SO |
RS |
. |
> |
N |
^ |
n |
~ |
|
F |
SI |
US |
/ |
? |
O |
_ |
o |
DEL |
Op de vertikale as van de tabel staat het minst significante cijfer, en op de horizontale as het meest significante cijfer van de hexadecimale code voor de letters, cijfers, leestekens en speciale tekens.
Bijvoorbeeld:
Enkele speciale tekens die U in de cursus nog zult tegenkomen zijn:
-
ESC escape, de code die gegenereerd wordt door de 'Esc' toets
-
CR carriage return, de code die gegenereerd wordt door de 'Enter' toets
-
LF line feed
-
BEL bel
-
BS backspace
-
SP space, de code voor een spatie
De ASCII code is een 7-bits code. Meestal wordt voor elke code een byte gereserveerd, waarin dan één bit over is. Het is gebruikelijk om dit bit '0' te laten.
|