HOME
- - - - - - - - - - - - - - - Other material for programmers
- - - - - - - - - Pascal Tutorials Table of Contents
- - - - - - - - - Arduino Tutorials Table of Contents
Overview of Binary, with Pascal and C code.
The people working on the hardware of early computers were delighted when the software people told them that only two states were needed inside the machine. You or I might try to make an analog computer, one that used, say, 1 volt to stand for "1", 2 volts to stand for "2", etc. Making such circuits is possible.... just tedious. It is easier to make circuits which only need to be "clever" enough to hold two values, usually called "off" and "on", or "zero" and "one". I'm not espousing the belief that "easy=good", but if you can avoid the complications of showing 1,2,3... with different voltage levels, then you can spend more time making your machine more reliable, and more clever in other ways.
We call the two state computers "digital", even though "binary" would be a better name.
So. Everything inside the computer is, at one level, a one or a zero. How?
Think first about the decimal numbers we use every day. Even though we only have 10 digits (0,1,2,3...8,9), we can still show numbers bigger than 9, can't we? Likewise in the binary system we can show numbers bigger than 1 by using several BInary digiTs (often called "bits") together. It is the same thing that we do with language. 26 letters. Many, many words. Within the computer, groups of bits are accessed together, often groups of eight. A group of 8 bits is called a byte. I believe the view that says "byte" came from talking about using the bits "eight-by-eight", as in "the animals entered 2-by-2". At the time "byte" was coming into use, using bits in 8 bit groups was not as common as it is today. The first computer I programmed worked with 12 bit groups. Though we won't use it again, I'll mention in passing that the word "word" is used when talking about the number of bits usually used by the computer being discussed. Thus, even though "byte" always means 8 bits, the number of bits in a word varies from computer to computer. (It also has another use.)
All computers have long lists of numbers stored in them. At least one of those lists is not lost when the computer is switched off. (Such a list is called "non-volatile") The computers are built so that when they are turned on, the number at the head of a particular one of those non-volatile lists is fetched into a special place in the computer. That number tells the computer what to do next. In some cases more information is needed for what comes next, and that information will be held in the next number in the list. I'm slightly oversimplifying here, but not too much, when I say that the first number might have been a general code for "You need to put something on the monitor". Built into that instruction would be that WHAT to put on the monitor is to be found as the next number in the list, and that the number is held in the ASCII code. Now, written in binary, the code for "A" is 01000001. In the simplest code (there are others) for converting binary to decimal, 01000001 is 65... but who cares? At the moment, the 1s and 0s are being interpreted as a way of specifying squiggles which "mean" nothing to the computer. It just puts those squiggles on the monitor, and our brains interpret them.
So... one group of eight 1s and 0s... one byte... may be a code for what the electronics should do. Another byte may be a code for a squiggle. In another scenario, the instruction might be for putting a number of squiggles on the monitor. The first byte after the instruction might again say WHICH squiggle, and the second number after the instruction might be a code for HOW MANY of them to put on the screen. At last! A byte standing for a number!
How does the computer tell an instruction-byte from a squiggle-byte from a number-coding-byte? It's all in how you came to it. Thus the need for the computer to start up at a known place in a non-volatile list of bytes. The first one WILL be interpreted as an instruction. Subsequent bytes will be interpreted according to the demands of the bytes which have come before them.
So how does the computer ever do anything beyond a single, repeated task? There are ways to get bytes into the electronics via a keyboard. The computer will be programmed to do various waking-up tasks, and then it will settle into a loop that says "Have I been asked to do anything?" If not, it just asks the question again. If, however, the human outside has pressed a key on the keyboard, or moved the mouse, or similar, then the computer can "see" that, and "see" which key. Depending on which key, it then moves on to other lists of bytes, and works its way through them. The numbers in those lists may change, either because the human types in new stuff, or because the human instructs the computer to go fetch a list from, say, a disc.
SOMETIMES (not always) we need to be able to convert between binary numbers and decimal numbers. Do remember that either is merely one way of writing something, another "code". "12", "twelve", "a dozen", "douze" and "6+6" are all the same thing, really.
IF we are using simple binary numbers 100 and 4 are two ways of writing the number of fingers on a hand (not counting the thumb.)
We talked elsewhere about converting from bytes to numbers. To recap:
In the simplest binary to decimal conversion scheme...
The decimal number 0 is the binary number 0
The decimal number 1 is the binary number 1
The decimal number 2 is the binary number 10
" 3 " 11...
Decimal... binary...
4 100
5 101
6 110
7 111
8 1000
9 1001
10 1010... etc.
....
......
252 11111100
253 11111101
254 11111110
255 11111111
Note that in this simplest binary, the biggest number you can show is 255, just as if my car only has 5 wheels on it's odometer, no matter how far I drive it, at worst it will only ever show that I've been 99,999 miles.
Now.. to convert from binary to decimal: The "secret" is to know that the columns have values. The right hand-most column is worth 1. The next to the left is worth 2, the next 4, the next 8, and so on: 16, 32, 64, 128.
You use the column value information as follows:
binary 1000 would be equivalent to 8 (4th column's worth:8)
binary 1001 would be equivalent to 9 (1+8.. it is easiest to work from right to left)
binary 1011 would be equivalent to 11 (1+2+8)
Converting from decimal to this simple binary isn't something I often need to do, but it can be done. That process is best done from left to right: If you wanted the binary for 67, you would proceed as follows...
83 must be shown by 1xxxxxx, by which I mean "a 1 in the 7th column from the right, and as-yet-to-be-determined 1s and 0s in the other columns. Any simple binary number with a 1 in the 7th column is worth 64 plus something, due to the value of the 7th column. 83 is 19 more than 64, so the other 1s and 0s must be worth 19. There would be a 0 in the 6th column, because, after accounting for 64 with the first 1, there's no 32 to account for. So our answer so far is 10xxxxx. Putting a 1 in the 5th column from the right accounts for another 16, so there's 3 left to account for. Answer so far: 101xxxx. With only 3 left to account for, we put 0s in the "8" and "4" columns. Answer so far: 10100xx. A 1 in the second column is worth 2, leaving one to be accounted for, and, not coincidentally the remaining column is worth 1. Final answer: 1010011.
I keep talking about "simple" binary. ANY code using only 1s and 0s is a binary code. Any number made of 1s and 0s is a binary number. As long as the writer and the reader are agreed on what system is to be used, all is well. I'm going to talk for a while about other codes which are useful in some circumstances. Further down the page (after the next horizontal line) I'm going to talk about bitwise operations... something else you do with numbers in computers.
Suppose you want to store serial numbers from 0 to 9999 in the computer. One scheme that might be used is binary coded decimal, BCD. For this, you'd use two bytes per serial number. Each byte would be looked at in two halves. (4 bits is called a nibble... really!) To code 1234 in this scheme, you'd store 0001 0010 0011 0100. There are disadvantages to BCD, but it does have the advantage of being easy to work with after just a little getting used to it.
If you have cause to do much work with binary numbers, you soon learn another notation, called hex. Hex is a little like BCD. You still look at the byte in two nibbles, however, you allow ANY combination in each half. Some hex numbers are the same as the BCD equivalent, e.g.:
Binary: 00000010 00100011 10011001
Hex: 02 23 99
What do you do, though, when then nibble is equivalent to decimal 10? In that case, you write an A, and so on:
Binary Decimal Hex
1010 10 A
1011 11 B
1100 12 C
1101 13 D
1110 14 E
1111 15 F
Once you've agreed this, you can write any byte with just two characters, e.g. 11111111 is FF.
There are ways to say whether 11 should be treated as a decimal 11, a binary 11 (same as 3 in decimal), or as hex 11 (same as 17 in decimal.) If you have subscripts, you suffix 10, 2 or 16 respectively. Putting an H or a $ in front of, say, 11, e.g. $11 usually signifies you mean hex 11. A B or % is used to denote binary.
When working with numbers in the computer, it is common to include leading zeros. While we would rarely write 025 in everyday life, it isn't odd to write 00010001 when dealing with numbers for the computer. It makes clear that no digits have been left out by mistake. Naval helmsmen would never say they were steering a course of 25; they'd call it zero two five, to make clear that they hadn't failed to hear, say, one two five.
What about negative numbers? If you use the leftmost bit in the byte to convey sign, 00000001 could be positive 1 and 10000001 could be negative one. Something a bit like this is commonly used... but with a twist there isn't time to go into here. The system is called "two's complement arithmetic" if you want to look it up elsewhere.
Numbers with a fractional part get even more exciting. Basically, you have to trade off three things (besides complexity). You can strike many compromises between...
The number of bytes needed to store the number
The biggest number you can show (no system has no limit.)
The accuracy you can achieve.
We'll only look at the last of those, and that only briefly. If you said "I need to be able to show 0 to 255,000, but only to the nearest 1,000", I'd say to you: Put the number of thousands in a byte. 00000001 would mean 1,000. 11111111 (255 in simple decimal) would mean 255,000. Problem solved... but at a price.
And so far we've only done codes for showing numbers with 1s and 0s!
qTO DO: ASCII, EXOTICS.
Bitwise Operations.
Suppose you had a computer controlling the heating in a mansion. Suppose the heat to each room could be turned on or off separately. You might have a computer program in charge. that program might store the current setting of each room in a separate variable... a variable using up 8 bits of the computers memory.... OR you might get clever, and "code" the ons and offs into a single byte of memory. For the home heating example, the saving would be too small to be worth the hassle, but similar tricks are worthwhile in other situations.
So.. now instead of the left hand most column of the byte being worth 128, as it would be in a simple binary code, the bit there might stand for sitting room heat on (if 1) or off (if zero). the next column could indicate the state required in the kitchen, the next byte the bedroom, etc.
How are we going to work with individual bits out of the byte?
You may have read elsewhere in this tutorial of the AND, OR, and XOR operations. Elsewhere I've written about them as Boolean operators, and all i said was true. However, they can also be applied as follows:
If you AND the following binary numbers together, you get the result shown. Note I am (correctly!) using the word "AND" as a verb. It doesn't have to be capitalized to keep Pascal happy, but I will do that here to distinguish this use from ANDs everyday use.
110011 First number
111000 Second number
110000 First AND Second answer
You only need to know that when ANDing numbers, you work on each column separately. You also need to know that the answer to (1 AND 1) is 1, but (0 AND 1), or (1 AND 0), or (0 AND 0) all equal 0. The answer is 1 only when the first AND the second bit going into the answer are 1s.
Because that last paragraph is hard to read, the following way of showing such things was invented. It is called a truth table.
AND: A
0 1
-------
0 | 0 0
B |
1 | 0 1
"A" and "B" are the inputs, i.e. the bits being ANDed together. Each can be a 1 or a 0. You just look at the relevant intersection in the grid to find out the answer to any particular combination of 1s and 0s in A and B
Give this a try, be sure you can see that the answer is right:
100011 First number
110110 Second number
100010 First AND Second answer
The OR rule works as follows:
OR: A
0 1
-------
0 | 0 1
B |
1 | 1 1
And the other important rule, the XOR rule, works as follows:
XOR: A
0 1
-------
0 | 0 1
B |
1 | 1 0
Now that we have those tools, I can show you how to change the bit which codes for the heat in, say, the kitchen to be on. Remember: The kitchen was coded with the bit in the 7th column. (A little aside for you: That's often called column 6, as the right hand column is often called column zero.)
Early in your program, in the part executed only once, you would set up something called mKitchenOn. "m" for "mask", which is being used here in the sense of "stencil". In mKitchenOn, you would store 01000000. (You could also use a constant, if you know about them. Best way to go for this.)
Assume you are storing the state for the heating in a variable called bHeat. All you need to do to turn the heat on is....
Pascal version....
bHeat:=bHeat OR mKitchenOn;
Arduino (C) version...
TO BE DONE STILL...
Writing X's for bits who's state we don't need to know about for the narrow question of whether what I've said will work will work, we can analyze my proposal as follows
xxxxxxxx bHeat before OR operation
01000000 mKitchenOn
x1xxxxxx result of OR operation.
No matter what the 7th column bit was in bHeat, after ORing with the 1 in mKitchenOn, it will be a 1. All the other bits will be as they were before. Either you ORd a 1 with a 0, leaving the 1 you started with, or you ORd a 0 with a 0, leaving the 0 you started with. Cool?!
What if you want to make the bit a 0? Set up a mask mKitchenOff which is 10111111, and do
Pascal version....
bHeat:=bHeat AND mKitchenOff;
Arduino (C) version...
TO BE DONE STILL...
You can check this the same way as we checked the ORing
xxxxxxxx bHeat before AND operation
10111111 mKitchenOff
x0xxxxxx result of OR operation.
How can we see whether the bit in the 7th column is a 1 or a 0, regardless of what the other bits are? The following does the job, even if the name for the mask may mislead in this use.
Pascal version....
if (bHeat AND mKitchenOn) = 0 then begin
{Kitchen bit was 0}
DoWhatYouLike;
end
else begin
{Kitchen bit was 1}
DoTheOtherThing;
end
Arduino (C) version...
TO BE DONE STILL...
That's all for now!
To search THIS site.... (Go to the site's above, and use their search buttons if you want to search them.)...
Way to search this site without using forms
Ad from page's editor: Yes.. I do enjoy
compiling these things for you... hope they are helpful. However..
this doesn't pay my bills!!! If you find this stuff useful, (and you
run an MS-DOS or Windows PC ) please visit my freeware and shareware
page, download something, and circulate it for me? Links on your page
to this page would also be appreciated!
Click here
to visit editor's freeware, shareware page.
Link to editor's (Arunet) homepage
How to email or write this page's editor, Tom Boyd