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.