Professional Documents
Culture Documents
Computing Fundamentals
Many programmers nowadays start programming from a high-level language like
C++ or Java or C#. They learn the basics of the language, learn about algorithms and
data structures, and pick up a few “tricks” along the way. Many of the programmers
unfortunately are ignorant to the lower level mechanics of the machine they’re
programming. In days when dinosaurs roamed the earth, you had to learn the low level
nitty gritty stuff, which took roughly a couple weeks, before even being able to write
your first program. This article series is meant to give you a general idea of what goes on
in the machine when you instruct it to do something. It will take a journey from the bits
and transistors and march to the top. Hopefully, the article will give you enough
information to read other books on the subject that cover’s this subject intensively.
Problem Statement
Algorithm
Implementation Language
Operating System
Assembly Language
Instruction Set Architecture
MicroArchitecture
Combinatorial Circuits
Logic Gates
Transistors
Stuff only science can explain
Table 1: The Layers
Many programmers are familiar with the top 3 layers but are ignorant of the lower
layers. The article will start from the next to last layer, the transistor, and move up in
subsequent articles. But before learning about transistors we have to take a prerequisite
sidetrack and learn about data representation, integer and bitwise operations.
At the most fundamental level, a computer only understands bits. No matter what
language you use or what run-time you run a program on, it all gets translated into binary
bits. A bit is the most fundamental piece of information in a computer. It is either on or
off, representing high and low electrical states (more on this in the transistor section).
Generally speaking a group of 8-bits is called a byte, 16-bits are called a word (although
this term does have a somewhat ambiguous meaning), 32 bits is a double-word, and 64-
bits is called a quad-word. The computer uses a binary (base 2) number system, so it
makes a bit of sense to cover this briefly.
The binary system in 5 minutes
0
1
Since a computer uses the binary system, this is all that it is capable of counting up to
using only these two digits. In the base-10 system, we have:
0
1
2
3
4
5
6
7
8
9
Ok, we can count to ten in the base-10 system, do we stop and say: “That’s all we can do
with base 10, since we ran out of fingers/symbols”. No, instead, we repeat that sequence
again except we place a 1 at the front:
10
11
12
13
14
15
16
17
18
19
Ok, so we got 10 more numbers, do we stop and say “That’s all we ran out of toes” or
“That’s all we’re capable of doing”? No, we repeat the original sequence and add a 2 at
the beginning:
20
21
22
23
24
25
26
27
28
29
When we get to 99, do we stop and give up? Being human, no, we apply the same
concept again: we repeat numbers 0 to 99 and add a 1 at the beginning (we do have to
add a place-holder for the first ten numbers so that they are two digits: 00, 01, 02,…, 09).
Going back to the base-2 system, to count beyond 2, we just do the same thing, we repeat
the sequence and add a 1 to the beginning:
10
11
And we get numbers 2 and 3. Applying this technique again, we repeat the original
sequence up to this point and add a one at the beginning getting:
100
101
110
111
1010
1011
1100
1101
1110
1111
Which is 10, 11, 12, 13, 14, and 15. Putting it all in chart form, we have:
There are a couple of tricks you may want to keep in mind when going from
binary to decimal. Look at the binary representation for 10 and 11, specifically, the two
low order bits. Also, look at numbers that are powers of 2 (2, 4, 8, 16, etc.). Look at
their binary counterpart and count the number of zeros, you’ll notice that it’s always 2n
where n = number of zeros (eg. Binary 1000, there are 3 zero’s so in base-10, it’s 23 or 8).
And also look at the binary numbers that have all 1’s. You’ll notice that it’s always one
less then a power of 2, so given n 1’s the decimal representation is 2n – 1 (eg. Binary 111,
there are 3 one’s so in base-10, it’s 23 – 1 or 7).
You first examine the high-order bit (called the sign-bit or the most-significant bit
or the leftmost bit). If the sign bit is 0, then the number is positive and you interpret it the
usual way. To find the magnitude when the sign bit is 1, you first invert all the bits
(make a 0 into a 1 and vice-versa, otherwise known as a bitwise NOT) and then add 1.
Binary addition is pretty simple since we are only dealing with two digits. If we
add a zero to a one (or vice-versa) the answer is always 1. Zero plus zero is always zero
and one plus one is three.
0+0 0
0+1 1
1+0 1
1+1 11
Table 2: Binary addition (results are all in binary)
Since we are told to interpret it as a signed number, we examine the high order bit, which
is a 1, telling us it’s a negative number. To find the magnitude, we invert the bits getting
0100 and then add a 1 giving us 0101 or 5. So the answer is -5.
The high-order bit tells us it is a negative number, so we invert the bits which gives us
0111. We add 1 which gives us 1000 (yes the original number) and the answer is -8.
We examine the sign bit and it tells us that it’s a zero, so it’s a positive number; we
interpret it the usual way, which gives us the answer 1.
1 is represented as 0001. We then perform the 2’s complement operation as usual (it’s a 2
way operation), we invert all the bits (giving us 1110), and add 1, giving us the final
result: 1111.
We know how to add two numbers, but what about subtraction? If you remember
from pre-algebra, subtraction is simply adding the opposite. That is, 13 – 5 is the same as
13 + (-5). We know how to represent negative numbers and we know how to add in
binary, so it looks like we don’t have any problems. 13 -> 01101 and -5 -> 11011 and
adding them together, 01101 + 11011, gives us: 01000 (8) with an extra 1 as an overflow
(overflow will be covered in next 2 paragraphs). So we see why the 2’s complement
notation is used, it gives us the correct answer when we add and subtract two numbers.
Just for reference, the predecessor to the 2’s-complement type was the 1’s-
complement, which is like the 2’s complement except it didn’t add a 1 in the final step,
and the signed-magnitude type, which simply used the high-order bit to determine
whether to interpret an integer as signed or unsigned. Both of these data types were used
at one point back on early machines. Both required special hardware to do addition, so
the 2’s-complement type was devised.
Sometimes when we add two numbers together, we get an extra digit, the carry or
overflow bit. An overflow means that the result could not be fully expressed given the
number of output bits available. For instance, if we are limited to 1-bit inputs and 1 bit
for output, then given 1 + 1 = 10, the result is 0 but with a 1 as the carry or overflow. It's
pretty easy to determine if there's an overflow when adding unsigned numbers, just check
if the result has a carry. For signed numbers, you have to use a more subtle test. To
detect signed overflow, if you add a positive number and a negative number, then the
result cannot overflow. If you add two negative numbers and the result is positive, then
the result has overflowed. Similarly, if you add two positive numbers and the result is a
negative number then you have an overflow.
• Bitwise NOT inverts a bit. That is, if a bit is 0, then it changes it to a 1 and vice-
versa.
• Bitwise AND takes two bits and performs a so-called logic AND operation.
o If the two bits are 1, then the result is 1. (1 AND 1 = 1)
o Any other combination produces a 0.
1 AND 0 = 0
0 AND 1 = 0
0 AND 0 = 0
• Bitwise OR takes two bits and performs a so-called logic OR operation
o If the two bits are 0, then the result is 0. (0 OR 0 = 0)
o Any other combination gives a 1
1 OR 1 = 1
1 OR 0 = 1
0 OR 1 = 1
Although there are many types of transistors, they all work on a similar principle.
There is a power source that comes in one end of the transistor and goes out another end.
Which end it goes out depends on whether the switch (sometimes called the gate) inside
the transistor is open or closed. A conceptual rendering is shown below.
Figure 1: A schematic rendering of a transistor
When a certain amount of voltage, say between 2-3 volts, is supplied to the base
(from now on we’ll call IN), then the gate is closed and power flows from VCC (source)
to Emitter (ground). When there is very little voltage supplied from IN, say 0-1 volts, the
gate is open and power flows from the source to the Collector (herein called OUT). How
much power is necessary to affect the gate is highly dependant on the transistor (type of
transistor, material used to construct it, etc). For our purposes we will neatly ignore the
amount of current necessary in order to affect the gate. Instead, we will use the logical
equivalents: if the gate is closed and current is allowed to flow to OUT, we will denote a
one at the output. If the gate is open and current is directed to ground, then we will
denote a zero at the output.
Logic gates are constructed from transistors. Logic gates can be seen as the next
step up from transistors. They allow us to construct circuits that implement the bit
operations in the previous section (bitwise NOT, AND, and OR). If you look carefully,
Figure 1 is also your very first logic gate. It is called an inverter. If a 0 is being pushed
from IN, then a 1 will be pushed on OUT, likewise, if a 1 is pushed from IN, then a 0 will
be pushed on OUT. If you look carefully, the operation of the inverter models after the
bitwise NOT function.
If you take two transistors and connect them in a series circuit, then you will have
something like the image below.
IN 1 IN 2 OUT
0 0 1
0 1 1
1 0 1
1 1 0
If we wire the transistors in a parallel circuit, then we will get another logic gate
shown below, called the NOR (Not OR) gate. If there is no power coming from both IN
1 and IN 2, then both the transistor gates are open and current flows from source to OUT.
Any other combination would have current flow from source to either ground. Again, if
we use the logical equivalent, if we push a 0 into both IN 1 and IN 2, then a 1 will be
pushed onto OUT. Any other combination being pushed into IN 1 or IN 2 will result in a
0 being pushed onto OUT.
IN 1 IN 2 OUT
0 0 1
0 1 0
1 0 0
1 1 0
Figure 4: Truth table for a NOR gate
The three gates that you see above are the three basic building blocks for building
any type of digital logic. If we route the output of either the NOR gate or the NAND gate
through an inverter, then we get the corresponding OR gate and AND gate.
Figure 5: An AND gate
Figure 6: An OR gate
As you can see, AND gates and OR gates require 3 transistors each. This is one
reason why many circuits are built using NAND gates and NOR gates. They are simpler
and require fewer transistors. However, when designing circuits on paper, AND gates
and OR gates are initially used since they are logically simpler to work with for the
human mind.