CS212 - Computer Organization with Assembly Language
Computer System
A digital computer consists of an interconnected system of processors, memories, and
input/output devices. This chapter is an introduction to these three components and to their
interconnection, as background for a more detailed examination of the specific levels in the five
subsequent chapters. Processors, memories, and input/output are key concepts and will be present
at every level, so we will start our study of computer architecture by looking at all three in turn.
PROCESSORS
The organization of a simple bus-oriented computer. The CPU (Central Processing Unit) is
the ‘‘brain’’ of the computer. Its function is to execute programs stored in the main memory by
fetching their instructions, examining them, and then executing them one after another. The
components are connected by a bus, which is a collection of parallel wires for transmitting address,
data, and control signals. Buses can be external to the CPU, connecting it to memory and I/O
devices, but also internal to the CPU, as we will see shortly. Modern computers have multiple
buses.
The CPU is composed of several distinct parts. The control unit is responsible for fetching
instructions from main memory and determining their type. The arithmetic logic unit performs
operations such as addition and Boolean AND needed to carry out the instructions.
Figure 1 The organization of a simple computer with one CPU and two I/O devices
The CPU also contains a small, high-speed memory used to store temporary results and certain
control information. This memory is made up of a number of registers, each having has a certain
size and function. Usually, all the registers have the same size. Each register can hold one number,
up to some maximum determined by its size. Registers can be read and written at high speed since
they are internal to the CPU.
1
CS212 - Computer Organization with Assembly Language
The most important register is the Program Counter (PC), which points to the next instruction
to be fetched for execution. ( The name ‘‘program counter’’ is somewhat misleading because it
has nothing to do with counting anything, but the term is universally used.) Also important is the
Instruction Register (IR), which holds the instruction currently being executed. Most computers
have numerous other registers as well, some of them general purpose as well as some for specific
purposes. Yet other registers are used by the operating system to control the computer.
CPU Organization
The internal organization of part of a simple von Neumann CPU is shown in Fig. 2-2 in more
detail. This part is called the data path and consists of the registers (typically 1 to 32), the ALU
(Arithmetic Logic Unit), and several buses connecting the pieces. The registers feed into two
ALU input registers, labeled A and B in the figure. These registers hold the ALU input while the
ALU is performing some computation. The data path is important in all machines.
Figure 2 The data path of a typical von Neumann machine
The ALU itself performs addition, subtraction, and other simple operations on its inputs, thus
yielding a result in the output register. This output register can be stored back into a register. Later
on, the register can be written (i.e., stored) into memory, if desired. Not all designs have the A, B,
and output registers. In the example, addition is illustrated, but ALUs can also perform other
operations. Most instructions can be divided into one of two categories: register-memory or
2
CS212 - Computer Organization with Assembly Language
register-register. Register-memory instructions allow memory words to be fetched into registers,
where, for example, they can be used as ALU inputs in subsequent instructions. (‘‘Words’’ are the
units of data moved between memory and registers. A word might be an integer. We will discuss
memory organization later in this chapter.) Other register-memory instructions allow registers to
be stored back into memory.
The other kind of instruction is register-register. A typical register-register instruction fetches
two operands from the registers, brings them to the ALU input registers, performs some operation
on them (such as addition or Boolean AND), and stores the result back in one of the registers. The
process of running two operands through the ALU and storing the result is called the data path
cycle and is the heart of most CPUs. To a considerable extent, it defines what the machine can do.
Modern computers have multiple ALUs operating in parallel and specialized for different
functions. The faster the data path cycle is, the faster the machine runs.
RISC versus CISC
During the late 70s there was experimentation with very complex instructions, made possible
by the interpreter. Designers tried to close the ‘‘semantic gap’’ between what machines could do
and what high-level programming languages required. Hardly anyone thought about designing
simpler machines, just as now not a lot of research goes into designing less powerful spreadsheets,
networks, Web servers, etc. (perhaps unfortunately).
One group that bucked the trend and tried to incorporate some of Seymour Cray’s ideas in a
high-performance minicomputer was led by John Cocke at IBM. This work led to an experimental
minicomputer, named the 801. Although IBM never marketed this machine and the results were
not published until years later (Radin, 1982), word got out and other people began investigating
similar architectures.
In 1980, a group at Berkeley led by David Patterson and Carlo Se´quin began designing VLSI
CPU chips that did not use interpretation (Patterson, 1985, Patterson and Se´quin, 1982). They
coined the term RISC for this concept and named their CPU chip the RISC I CPU, followed shortly
by the RISC II. Slightly later, in 1981, across the San Francisco Bay at Stanford, John Hennessy
designed and fabricated a somewhat different chip he called the MIPS (Hennessy, 1984). These
chips evolved into commercially important products, the SPARC and the MIPS, respectively.
These new processors were significantly different than commercial processors of the day.
Since they did not have to be backward compatible with existing products, their designers were
free to choose new instruction sets that would maximize total system performance. While the initial
emphasis was on simple instructions that could be executed quickly, it was soon realized that
designing instructions that could be issued (started) quickly was the key to good performance.
How long an instruction actually took mattered less than how many could be started per second.
At the time these simple processors were being first designed, the characteristic that caught
everyone’s attention was the relatively small number of instructions available, typically around
50. This number was far smaller than the 200 to 300 on established computers such as the DEC
VAX and the large IBM mainframes. In fact, the acronym RISC stands for Reduced Instruction
Set Computer, which was contrasted with CISC, which stands for Complex Instruction Set
Computer (a thinly veiled reference to the VAX, which dominated university Computer Science
3
CS212 - Computer Organization with Assembly Language
Departments at the time). Nowadays, few people think that the size of the instruction set is a major
issue, but the name stuck.
Design Principles for Modern Computers
RISC design principles, that architects of new general-purpose CPUs do their best to follow.
External constraints, such as the requirement of being backward compatible with some existing
architecture, often require compromises from time to time, but these principles are goals that most
designers strive to meet.
All Instructions Are Directly Executed by Hardware
All common instructions are directly executed by the hardware. They are not interpreted by
microinstructions. Eliminating a level of interpretation provides high speed for most instructions.
For computers that implement CISC instruction sets, the more complex instructions may be broken
into separate parts, which can then be executed as a sequence of microinstructions. This extra step
slows the machine down, but for less frequently occurring instructions it may be acceptable.
Maximize the Rate at Which Instructions Are Issued
Modern computers resort to many tricks to maximize their performance, chief among which is
trying to start as many instructions per second as possible. After all, if you can issue 500 million
instructions/sec, you have built a 500-MIPS processor, no matter how long the instructions actually
take to complete. (MIPS stands for Millions of Instructions Per Second. The MIPS processor was
so named as to be a pun on this acronym. Officially it stands for Microprocessor without
Interlocked Pipeline Stages.) This principle suggests that parallelism can play a major role in
improving performance, since issuing large numbers of slow instructions in a short time interval
is possible only if multiple instructions can execute at once. Although instructions are always
encountered in program order, they are not always issued in program order (because some needed
resource might be busy) and they need not finish in program order. Of course, if instruction 1 sets
a register and instruction 2 uses that register, great care must be taken to make sure that instruction
2 does not read the register until it contains the correct value. Getting this right requires a lot of
bookkeeping but has the potential for performance gains by executing multiple instructions at
once.
Instructions Should Be Easy to Decode
A critical limit on the rate of issue of instructions is decoding individual instructions to
determine what resources they need. Anything that can aid this process is useful. That includes
making instructions regular, of fixed length, and with a small number of fields. The fewer different
formats for instructions, the better.
Only Loads and Stores Should Reference Memory
One of the simplest ways to break operations into separate steps is to require that operands for
most instructions come from—and return to—CPU registers. The operation of moving operands
from memory into registers can be performed in separate instructions. Since access to memory can
take a long time, and the delay is unpredictable, these instructions can best be overlapped with
other instructions assuming they do nothing except move operands between registers and memory.
4
CS212 - Computer Organization with Assembly Language
This observation means that only LOAD and STORE instructions should reference memory. All
other instructions should operate only on registers.
Provide Plenty of Registers
Since accessing memory is relatively slow, many registers (at least 32) need to be provided, so
that once a word is fetched, it can be kept in a register until it is no longer needed. Running out of
registers and having to flush them back to memory only to later reload them is undesirable and
should be avoided as much as possible. The best way to accomplish this is to have enough registers.
PRIMARY MEMORY
The memory is that part of the computer where programs and data are stored. Some computer
scientists (especially British ones) use the term store or storage rather than memory, although
more and more, the term ‘‘storage’’ is used to refer to disk storage. Without a memory from which
the processors can read and write information, there would be no stored-program digital
computers.
Bits
The basic unit of memory is the binary digit, called a bit. A bit may contain a 0 or a 1. It is the
simplest possible unit. (A device capable of storing only zeros could hardly form the basis of a
memory system; at least two values are needed.) People often say that computers use binary
arithmetic because it is ‘‘efficient.’’ What they mean (although they rarely realize it) is that digital
information can be stored by distinguishing between different values of some continuous physical
quantity, such as voltage or current. The more values that must be distinguished, the less separation
between adjacent values, and the less reliable the memory. The binary number system requires
only two values to be distinguished. Consequently, it is the most reliable method for encoding
digital information.
Memory Addresses
Memories consist of a number of cells (or locations), each of which can store a piece of
information. Each cell has a number, called its address, by which programs can refer to it. If a
memory has n cells, they will have addresses 0 to n −1. All cells in a memory contain the same
number of bits. If a cell consists of k bits, it can hold any one of 2k different bit combinations.
Figure 2-9 shows three different organizations for a 96-bit memory. Note that adjacent cells have
consecutive addresses
5
CS212 - Computer Organization with Assembly Language
Figure 3 Three ways of organizing a 96-bit memory
The significance of the cell is that it is the smallest addressable unit. In recent years, nearly all
computer manufacturers have standardized on an 8-bit cell, which is called a byte. The term
octet is also used. Bytes are grouped into words. A computer with a 32-bit word has 4
bytes/word, whereas a computer with a 64-bit word has 8 bytes/word. The significance of a word is
that most instructions operate
on entire words, for example, adding two words together. Thus a 32-bit machine will have 32-bit registers
and instructions for manipulating 32-bit words, whereas a 64-bit machine will have 64-bit registers and
instructions for moving, adding, subtracting, and otherwise manipulating 64-bit words.
Cache Memory
Historically, CPUs have always been faster than memories. As memories have improved, so
have CPUs, preserving the imbalance. In fact, as it becomes possible to put more and more circuits
on a chip, CPU designers are using these new facilities for pipelining and superscalar operation,
making CPUs go even faster. Memory designers have usually used new technology to increase the
capacity of their chips, not the speed, so the problem appears to be getting worse over time. What
this imbalance means in practice is that after the CPU issues a memory request, it will not get the
word it needs for many CPU cycles. The slower the memory, the more cycles the CPU will have
to wait.
As we pointed out above, there are two ways to deal with this problem. The simplest way is to
just start memory READs when they are encountered but continue executing and stall the CPU if an
instruction tries to use the memory word before it has arrived. The slower the memory, the greater
the penalty when it does occur. For example, if one instruction in five touches memory and the
memory access time is five cycles, execution time will be twice what it would have been with
instantaneous memory. But if the memory access time is 50 cycles, then execution time will be up
by a factor of 11 (5 cycles for executing instructions plus 50 cycles for waiting for memory).
6
CS212 - Computer Organization with Assembly Language
Figure 4 The cache is logically between the CPU and main memory
We can formalize this calculation by introducing c, the cache access time, m, the main memory access
time, and h, the hit ratio, which is the fraction of all references that can be satisfied out of the cache. In our
little example of the previous paragraph, h = (k - 1)/k. Some authors also define the miss ratio, which is 1
− h. With these definitions, we can calculate the mean access time as follows:
mean access time = c + (1 − h)m
Memory Packaging and Types
From the early days of semiconductor memory until the early 1990s, memory was
manufactured, bought, and installed as single chips. Chip densities went from 1K bits to 1M bits
and beyond, but each chip was sold as a separate unit. Early PCs often had empty sockets into
which additional memory chips could be plugged, if and when the purchaser needed them.
Since the early 1990s, a different arrangement has been used. A group of chips, typically 8 or
16, is mounted on a printed circuit board and sold as a unit. This unit is called a SIMM (Single
Inline Memory Module) or a DIMM (Dual Inline Memory Module), depending on whether it has
a row of connectors on one side or both sides of the board. SIMMs have one edge connector with
72 contacts and transfer 32 bits per clock cycle. They are rarely used these days. DIMMs usually
have edge connectors with 120 contacts on each side of the board, for a total of 240 contacts, and
transfer 64 bits per clock cycle. The most common ones at present are DDR3 DIMMS, which is
the third version of the double data-rate memories.
Figure 5Top view of a DIMM holding 4 GB with eight chips of 256 MB on each side
A typical DIMM configuration might have eight data chips with 256 MB each. The entire
module would then hold 2 GB. Many computers have room for four modules, giving a total
capacity of 8 GB when using 2-GB modules and more when using larger ones.
7
CS212 - Computer Organization with Assembly Language
A physically smaller DIMM, called an SO-DIMM (Small Outline DIMM), is used in
notebook computers. DIMMS can have a parity bit or error correction added, but since the average
error rate of a module is one error every 10 years, for most garden-variety computers, error
detection and correction are omitted.
Memory Hierarchies
The traditional solution to storing a great deal of data is a memory hierarchy. At the top are the
CPU registers, which can be accessed at full CPU speed. Next comes the cache memory, which
is currently on the order of 32 KB to a few megabytes. Main memory is next, with sizes currently
ranging from 1 GB for entry-level systems to hundreds of gigabytes at the high end. After that
come solid-state and magnetic disks, the current workhorses for permanent storage. Finally, we
have magnetic tape and optical disks for archival storage.
Figure 6A five -level memory hierarchy
Magnetic Disks
A magnetic disk consists of one or more aluminum platters with a magnetizable coating.
Originally these platters were as much as 50 cm in diameter, but at present they are typically 3 to
9 cm, with disks for notebook computers already under 3 cm and still shrinking. A disk head
containing an induction coil floats just over the surface, resting on a cushion of air. When a positive
or negative current passes through the head, it magnetizes the surface just beneath the head,
aligning the magnetic particles facing left or facing right, depending on the polarity of the drive
current. When the head passes over a magnetized area, a positive or negative current is induced in
the head, making it possible to read back the previously stored bits. Thus as the platter rotates
under the head, a stream of bits can be written and later read back
The circular sequence of bits written as the disk makes a complete rotation is called a track.
Each track is divided up into some number of fixed-length sectors, typically containing 512 data
bytes, preceded by a preamble that allows the head to be synchronized before reading or writing.
Following the data is an Error-Correcting Code (ECC), either a Hamming code or, more
8
CS212 - Computer Organization with Assembly Language
commonly, a code that can correct multiple errors called a Reed-Solomon code. Between
consecutive sectors is a small intersector gap. Some manufacturers quote their disks’ capacities in
unformatted state (as if each track contained only data), but a more honest measurement is the
formatted capacity, which does not count the preambles, ECCs, and gaps as data. The formatted
capacity is typically about 15 percent lower than the unformatted capacity.
Figure 7A portion of a disk track. Two sectors are illustrated
Figure 8 A disk with four platters.
IDE Disks
Modern personal computer disks evolved from the one in the IBM PC XT, which was a 10-
MB Seagate disk controlled by a Xebec disk controller on a plugin card. The Seagate disk had 4
heads, 306 cylinders, and 17 sectors/track. The controller was capable of handling two drives. The
operating system read from and wrote to a disk by putting parameters in CPU registers and then
calling the BIOS (Basic Input Output System), located in the PC’s built-in read-only memory.
The BIOS issued the machine instructions to load the disk controller registers that initiated
transfers.
9
CS212 - Computer Organization with Assembly Language
The technology evolved rapidly from having the controller on a separate board, to having it
closely integrated with the drives, starting with IDE (Integrated Drive Electronics) drives in the
mid 1980s. However, the BIOS calling conventions were not changed for reasons of backward
compatibility
Eventually, IDE drives evolved into EIDE drives (Extended IDE), which also support a second
addressing scheme called LBA (Logical Block Addressing), which just numbers the sectors
starting at 0 up until a maximum of 228-1.
Solid-State Disks
Disks made from nonvolatile flash memory, often called solid-state disks (SSDs), are growing
in popularity as a high-speed alternative to traditional magnetic disk technologies. The invention
of the SSD is a classic tale of ‘‘When they give you lemons, make lemonade.’’ While modern
electronics may seem totally reliable, the reality is that transistors slowly wear out as they are used.
Every time they switch, they wear out a little bit more and get closer to no longer working. One
likely way that a transistor will fail is due to ‘‘hot carrier injection,’’ a failure mechanism in which
an electron charge gets embedded inside a once-working transistor, leaving it in a state where it is
permanently stuck on or off. While generally thought of as a death sentence for a (likely) innocent
transistor, Fujio Masuoka while working for Toshiba discovered a way to harness this failure
mechanism to create a new nonvolatile memory. In the early 1980s, he invented the first flash
memory.
Figure 9 A flash memory cell
10
CS212 - Computer Organization with Assembly Language
Character Codes
Each computer has a set of characters that it uses. As a bare minimum, this set includes the 26
uppercase letters, the 26 lowercase letters, the digits 0 through 9, and a set of special symbols, such
as space, period, minus sign, comma, and carriage return.
In order to transfer these characters into the computer, each one is assigned a number: for
example, a = 1, b = 2, ..., z = 26, + = 27, − = 28. The mapping of characters onto integers is called
a character code. It is essential that communicating computers use the same code or they will not
be able to understand one another.
ASCII
One widely used code is called ASCII (American Standard Code for Information
Interchange). Each ASCII character has 7 bits, allowing for 128 characters in all. However,
because computers are byte oriented, each ASCII character is normally stored in a separate byte.
Figure 2-44 shows the ASCII code. Codes 0 to 1F (hexadecimal) are control characters and do not
print. Codes from 128 to 255 are not part of ASCII, but the IBM PC defined them to be special
characters like smiley faces and most computers still support them.
Unicode
The computer industry grew up mostly in the U.S., which led to the ASCII character set. ASCII
is fine for English but less fine for other languages. French needs accents (e.g., syste`me); German
needs diacritical marks (e.g., f¨ur), and so on. Some European languages have a few letters not
found in ASCII, such as the German ß and the Danish o/ . Some languages have entirely different
alphabets (e.g., Russian and Arabic), and a few languages have no alphabet at all (e.g., Chinese).
As computers spread to the four corners of the globe and software vendors want to sell products
in countries where most users do not speak English, a different character set is needed.
A group of computer companies decided to solve this problem by forming a consortium to
create a new system, called Unicode, and getting it proclaimed an International Standard (IS
10646). Unicode is now supported by programming languages (e.g., Java), operating systems (e.g.,
Windows), and many applications.
UTF-8
Although better than ASCII, Unicode eventually ran out of code points and it also requires 16
bits per character to represent pure ASCII text, which is wasteful. Consequently, another coding
scheme was developed to address these concerns. It is called UTF-8 UCS Transformation
Format where UCS stands for Universal Character Set, which is essentially Unicode. UTF-8
codes are variable length, from 1 to 4 bytes, and can code about two billion characters. It is the
dominant character set used on the World Wide Web. One of the nice properties of UTF-8 is that
codes 0 to 127 are the ASCII characters, allowing them to be expressed in 1 byte (versus 2 bytes
in Unicode). For characters not in ASCII, the high-order bit of the first byte is set to 1, indicating
that 1 or more additional bytes follow.
11
CS212 - Computer Organization with Assembly Language
Figure 10 The ASCII character set
12