NCL 106: Naming Registers

In the last lesson, our program used three registers:

MOVE r0 1
MOVE r1 0
MOVE r2 10

$again
ADD r1 r1 r0
INC r0
BLE $again r0 r2

D.TXT r1
D.BLT

Each register had a different job:

r0    current number
r1    running total
r2    ending number

We know what they mean because we just wrote the program.

But if you came back to it later, an instruction like:

ADD r1 r1 r0

doesn't tell you what r0 and r1 are being used for.

As programs use more registers, remembering what every numbered register means becomes increasingly difficult.

NCL lets us give them names.

Giving a register a name

We can give r0 the name #count:

#count r0

This is called an alias.

After defining the alias, we can use:

#count

anywhere we would have used:

r0

For example:

#count r0

MOVE #count 5
D.TXT #count
D.BLT

displays:

5

#count does not create another register.

It is another name for r0.

The same register

Because #count and r0 refer to the same register, we can demonstrate their relationship directly:

#count r0

MOVE #count 5
D.TXT r0
D.BLT

This displays:

5

We stored the value using the name #count and retrieved it using the name r0.

We can do the opposite as well:

#count r0

MOVE r0 5
D.TXT #count
D.BLT

Again, the program displays:

5

There aren't two values here. Both names refer to the same register.

For example:

#count r0

MOVE #count 5
INC r0
D.TXT #count
D.BLT

displays:

6

Changing r0 also changes the value we see through #count, because they are the same register.

You normally won't want to switch between the two names like this. Using the alias consistently makes the program easier to read.

Naming our registers

Let's return to the program from the last lesson.

We were using:

r0    current number
r1    running total
r2    ending number

We can give each register a name that describes its job:

#count r0
#total r1
#limit r2

Now we can replace the numbered register names throughout the program:

#count r0
#total r1
#limit r2

MOVE #count 1
MOVE #total 0
MOVE #limit 10

$again
ADD #total #total #count
INC #count
BLE $again #count #limit

D.TXT #total
D.BLT

This program works exactly the same way as the original.

Compare:

ADD r1 r1 r0
INC r0
BLE $again r0 r2

with:

ADD #total #total #count
INC #count
BLE $again #count #limit

The CPU performs the same operations in either case, but the aliases make the purpose of each register much easier for us to follow.

For example:

ADD #total #total #count

now tells us that we're adding the current count to the running total and storing the result back in the total.

And:

BLE $again #count #limit

compares the count against the limit.

We no longer need to remember that r0 is the count, r1 is the total, and r2 is the limit every time we read an instruction.

Following the named registers

Aliases can also make it easier to trace a program.

Instead of keeping track of:

r0    r1    r2

we can follow the values by their purpose:

Instruction #count #total #limit
MOVE #count 1 1
MOVE #total 0 1 0
MOVE #limit 10 1 0 10
ADD #total #total #count 1 1 10
INC #count 2 1 10
ADD #total #total #count 2 3 10
INC #count 3 3 10
ADD #total #total #count 3 6 10
INC #count 4 6 10
ADD #total #total #count 4 10 10
INC #count 5 10 10
ADD #total #total #count 5 15 10
INC #count 6 15 10

The values haven't become any simpler.

What has changed is that we no longer need a separate reminder of what each column represents.

When you're tracing a larger program, meaningful names can make it much easier to see what is changing and why.

Choosing useful names

Aliases can be named for whatever job a register has in your program.

For example, our program uses:

#count r0
#total r1
#limit r2

Another program might use those same registers for completely different purposes:

#width r0
#height r1
#area r2

There is nothing special about r0 that makes it a counter, or r1 that makes it a total.

Those were simply the jobs we chose for them in our program.

A useful alias describes what the register represents.

Try it

Here is another program using three numbered registers:

MOVE r0 1
MOVE r1 1
MOVE r2 5

$again
MUL r1 r1 r0
INC r0
BLE $again r0 r2

D.TXT r1
D.BLT

First, follow the program without changing it.

Keep track of r0, r1, and r2.

What does each register do?

What value does the program eventually display?

Once you understand what the registers are being used for, choose useful names for them.

Add aliases at the beginning of the program, then replace the numbered register names with those aliases.

There isn't necessarily only one good name for each register. Choose names that make the program's purpose clearer to you.

Run the named version and make sure it still produces the same result.

One value that never changes

Take another look at our earlier program:

#count r0
#total r1
#limit r2

MOVE #count 1
MOVE #total 0
MOVE #limit 10

$again
ADD #total #total #count
INC #count
BLE $again #count #limit

D.TXT #total
D.BLT

#count changes as the loop runs.

#total changes as the loop runs.

But what about #limit?

We put 10 into it:

MOVE #limit 10

and never change it again.

We gave a register a useful name, only to use that register to hold the same value for the entire program.

Do we really need a register for that?


In NCL 107: Naming Values, we'll give fixed values useful names of their own.