Inside the Machine: An Illustrated Introduction to Microprocessors and Computer Architecture (7 page)

Read Inside the Machine: An Illustrated Introduction to Microprocessors and Computer Architecture Online

Authors: jon stokes

Tags: #Computers, #Systems Architecture, #General, #Microprocessors

BOOK: Inside the Machine: An Illustrated Introduction to Microprocessors and Computer Architecture
7.02Mb size Format: txt, pdf, ePub

that I’ll describe later) attached to four registers, named A, B, C, and D for

convenience. The DLW-1 is attached to a bank of main memory that’s laid

out as a line of 256 memory cells, numbered #0 to #255. (The number that

identifies an individual memory cell is called an
address
.)

The DLW-1’s Arithmetic Instruction Format

All of the DLW-1’s arithmetic instructions are in the following
instruction

format
:

instruction source1, source2, destination

There are four parts to this instruction format, each of which is called a

field
. The
instruction
field specifies the type of operation being performed (for example, an addition, a subtraction, a multiplication, and so on). The

two
source
fields tell the computer which registers hold the two numbers being operated on, or the
operands
. Finally, the
destination
field tells the computer which register to place the result in.

As a quick illustration, an addition instruction that adds the numbers in

registers A and B (the two source registers) and places the result in register C

(the destination register) would look like this:

Code

Comments

add A, B, C

Add the contents of registers A and B and place the result in C, overwriting

whatever was previously there.

2 “DLW” in honor of the DLX architecture used by Hennessy and Patterson in their books on computer architecture.

12

Chapter 1

The DLW-1’s Memory Instruction Format

In order to get the processor to move two operands from main memory

into the source registers so they can be added, you need to tell the processor

explicitly that you want to move the data in two specific memory cells to two

specific registers. This “filing” operation is done via a memory-access instruc-

tion called the load.

As its name suggests, the load instruction loads the appropriate data from

main memory into the appropriate registers so that the data will be available

for subsequent arithmetic instructions. The store instruction is the reverse of

the load instruction, and it takes data from a register and stores it in a location in main memory, overwriting whatever was there previously.

All of the memory-access instructions for the DLW-1 have the following

instruction format:

instruction source, destination

For all memory accesses, the instruction field specifies the type of memory

operation to be performed (either a load or a store). In the case of a load, the source field tells the computer which memory address to fetch the data from,

while the destination field specifies which register to put it in. Conversely, in the case of a store, the source field tells the computer which register to take

the data from, and the destination field specifies which memory address to

write the data to.

An Example DLW-1 Program

Now consider Program 1-1, which is a piece of DLW-1 code. Each of the lines

in the program must be executed in sequence to achieve the desired result.

Line

Code

Comments

1

load #12, A

Read the contents of memory cell #12 into register A.

2

load #13, B

Read the contents of memory cell #13 into register B.

3

add A, B, C

Add the numbers in registers A and B and store the result in C.

4

store C, #14

Write the result of the addition from register C into memory cell #14.

Program 1-1: Program to add two numbers from main memory

Suppose the main memory looked like the following before running

Program 1-1:

#11

#12

#13

#14

12

6

2

3

Basic Computing Concepts

13

After doing our addition and storing the results, the memory would be

changed so that the contents of cell #14 would be overwritten by the sum of

cells #12 and #13, as shown here:

#11 #12 #13 #14

12 6 2 8

A Closer Look at Memory Accesses: Register vs. Immediate

The examples so far presume that the programmer knows the exact memory

location of every number that he or she wants to load and store. In other

words, it presumes that in composing each program, the programmer has at

his or her disposal a list of the contents of memory cells #0 through #255.

While such an accurate snapshot of the initial state of main memory may

be feasible for a small example computer with only 256 memory locations,

such snapshots almost never exist in the real world. Real computers have

billions of possible locations in which data can be stored, so programmers

need a more flexible way to access memory, a way that doesn’t require each

memory access to specify numerically an exact memory address.

Modern computers allow the
contents
of a register to be used as a memory address, a move that provides the programmer with the desired flexibility.

But before discussing the effects of this move in more detail, let’s take one

more look at the basic add instruction.

Immediate Values

All of the arithmetic instructions so far have required two source registers as

input. However, it’s possible to replace one or both of the source registers

with an explicit numerical value, called an
immediate value
. For instance, to increase whatever number is in register A by 2, we don’t need to load the

value 2 into a second source register, like B, from some cell in main memory

that contains that value. Rather, we can just tell the computer to add 2 to A

directly, as follows:

Code

Comments

add A, 2, A

Add 2 to the contents of register A and place the result back into A,

overwriting whatever was there.

14

Chapter 1

I’ve actually been using immediate values all along in my examples, but

just not in any arithmetic instructions. In all of the preceding examples, each

load and store uses an immediate value in order to specify a memory address.

So the #12 in the load instruction in line 1 of Program 1-1 is just an immediate value (a regular whole number) prefixed by a # sign to let the computer

know that this particular immediate value is a memory address that desig-

nates a cell in memory.

Memory addresses are just regular whole numbers that are specially

marked with the # sign. Because they’re regular whole numbers, they can be

stored in registers—and stored in memory—just like any other number.

Thus, the whole-number contents of a register, like D, could be construed by

the computer as representing a memory address.

For example, say that we’ve stored the number 12 in register D, and that we

intend to use the contents of D as the address of a memory cell in Program 1-2.

Line

Code

Comments

1

load #D, A

Read the contents of the memory cell designated by the number

stored in D (where D = 12) into register A.

2

load #13, B

Read the contents of memory cell #13 into register B.

3

add A, B, C

Add the numbers in registers A and B and store the result in C.

4

store C, #14

Write the result of the addition from register C into memory cell #14.

Program 1-2: Program to add two numbers from main memory using an address stored in
a register

Program 1-2 is essentially the same as Program 1-1, and given the same

input, it yields the same results. The only difference is in line 1:

Program 1-1, Line 1

Program 1-2, Line 1

load #12, A

load #D, A

Since the content of D is the number 12, we can tell the computer to

look in D for the memory cell address by substituting the register name

(this time marked with a # sign for use as an address), for the actual

memory cell number in line 1’s load instruction. Thus, the first lines of

Programs 1-1 and 1-2 are functionally equivalent.

This same trick works for store instructions, as well. For example, if we

place the number 14 in D we can modify the store command in line 4 of

Program 1-1 to read as follows: store C, #D. Again, this modification would

not change the program’s output.

Basic Computing Concepts

15

Because memory addresses are just regular numbers, they can be stored

in memory cells as well as in registers. Program 1-3 illustrates the use of a

memory address that’s stored in another memory cell. If we take the input

for Program 1-1 and apply it to Program 1-3, we get the same output as if

we’d just run Program 1-1 without modification:

Line

Code

Comments

1

load #11, D

Read the contents of memory cell #11 into D.

2

load #D, A

Read the contents of the memory cell designated by the number in D

(where D = 12) into register A.

3

load #13, B

Read the contents of memory cell #13 into register B.

4

add A, B, C

Add the numbers in registers A and B and store the result in C.

5

store C, #14

Write the result of the addition from register C into memory cell #14.

Program 1-3: Program to add two numbers from memory using an address stored in a
memory cell.

The first instruction in Program 1-3 loads the number 12 from memory

cell #11 into register D. The second instruction then uses the content of D

(which is the value 12) as a memory address in order to load register A into

memory location #12.

But why go to the trouble of storing memory addresses in memory cells

and then loading the addresses from main memory into the registers before

they’re finally ready to be used to access memory again? Isn’t this an overly

complicated way to do things?

Actually, these capabilities are designed to make programmers’ lives

easier, because when used with the register-relative addressing technique

described next they make managing code and data traffic between the

processor and massive amounts of main memory much less complex.

Register-Relative Addressing

In real-world programs, loads and stores most often use
register-relative

addressing
, which is a way of specifying memory addresses relative to a

register that contains a fixed
base address
.

For example, we’ve been using D to store memory addresses, so let’s say

that on the DLW-1 we can assume that, unless it is explicitly told to do other-

wise, the operating system always loads the starting address (or base address)

of a program’s data segment into D. Remember that code and data are

logically separated in main memory, and that data flows into the processor

from a data storage area, while code flows into the processor from a special

code storage area. Main memory itself is just one long row of undifferentiated

memory cells, each one
byte
in width, that store numbers. The computer

carves up this long row of bytes into multiple segments, some of which store

code and some of which store data.

16

Chapter 1

A
data segment
is a block of contiguous memory cells that a program

stores all of its data in, so if a programmer knows a data segment’s starting

address (base address) in memory, he or she can access all of the other

memory locations in that segment using this formula:

base address + offset

where
offset
is the distance in bytes of the desired memory location from the data segment’s base address.

Thus, load and store instructions in DLW-1 assembly would normally

look something like this:

Code

Comments

load #(D + 108), A

Read the contents of the memory cell at location #(D + 108) into A.

store B, #(D + 108)

Write the contents of B into the memory cell at location #(D + 108).

In the case of the load, the processor takes the number in D, which is the

base address of the data segment, adds 108 to it, and uses the result as the

load’s destination memory address. The store works in the exact same way.

Of course, this technique requires that a quick addition operation (called

an
address calculation
) be part of the execution of the load instruction, so this is why the
load-store units
on modern processors contain very fast integer addition hardware. (As we’ll learn in Chapter 4, the load-store unit is the execution

unit responsible for executing load and store instructions, just like the

arithmetic-logic unit is responsible for executing arithmetic instructions.)

By using register-relative addressing instead of
absolute addressing
(in which memory addresses are given as immediate values), a programmer can write

programs without knowing the exact location of data in memory. All the

programmer needs to know is which register the operating system will place

the data segment’s base address in, and he or she can do all memory accesses

relative to that base address. In situations where a programmer uses absolute

addressing, when the operating system loads the program into memory, all

Other books

Laced Impulse by Combs, Sasha
If Only by Lisa M. Owens
Merlin's Booke by Jane Yolen
Our Vinnie by Julie Shaw
The Emerald Atlas by John Stephens
The Red Judge by Pauline Fisk
The Devil's Dictionary by Ambrose Bierce