# Microprocessors/Microcontrollers - Do registers have addresses?

My Embedded Systems professor keeps referring to the memory locations of registers as their respective "addresses". I'm confused by this; I was always under the impression that in any microprocessor, the CPU registers don't have addresses since they don't reside in the main memory (they reside in the microprocessor itself). I am also confused about what we refer to when we say the "memory location of the register" - again, it's not in main memory.

With that said, why are we referring to the locations of the CPU registers by "addresses"? Do all/some registers have addresses?

I thought about this and reasoned that maybe they're "connected" to certain main memory locations, allowing access to the values stored in the registers. To extend this thought, is this what memory mapping is?

I should also add that we are working specifically with NXP's LPC1768 microcontroller, which uses the ARM Cortex-M3 microprocessor.

It depends on the particular processor whether "registers" are in the same address space as regular data memory or separate. In either case, if there are multiple of them each one still needs a address.

Let's say the processor has 16 registers that are tightly coupled to the CPU and implemented separately from data memory. Those registers still have to be identified somehow. In this case, a 4 bit address would be needed to distinguish individual registers. In a RISC architecture, the 4-bit address of whatever register(s) a instruction worked on would be included in the instruction code. For example, the ADD instruction might add the value of a source register into a destination register. That instruction would include 4 bits to identify the source register and another 4 bits to identify the destination register. The documentation may refer to these registers by "number" 0 to 15, but that's really the address of where the registers lives in a special small memory by the CPU.

In addition to the above, even when a processor has special dedicated registers, those registers might be mapped into the general purpose data address space. References to those addresses are trapped and referred to the internal registers.

There are lots of schemes out there, but if you have more than one register, those registers need to be distinguished from each other somehow, and inside the hardware that will be with a "address", whether it is called that in the documentation or not.

• Ah, so there's the problem. I've always associated main memory/RAM with memory addresses, exclusively; I never would've thought to associate memory addresses with anything else. Thank you for clearing that up! – chevestong Mar 8 '13 at 0:11
• Also, now I'm curious; which component is the one responsible for locating and accessing these register addresses? – chevestong Mar 8 '13 at 0:12
• If they are dedicated registers there will be hardware just to select a register. Since there are so few registers, more hardware can be used to decode and act on the address bits that you could use in a normal large memory. This can make the decoding faster, allow for multiple ports, etc. Usually any one register can drive either ALU input and can save the ALU output. In some architecture (dsPIC is one example) three separate registers can be doing these things separately in the same instruction. – Olin Lathrop Mar 8 '13 at 12:42

The source of the confusion is that there are (in general) two kinds of things that can be called "registers".

The first is probably what you are familiar with: in ARM, it's registers R0, R1, R2, ... R12, SP, LR, PC and in x86 it's eax, ebx, ecx, edx, ebp, and so on. These can also be called "core registers" or "processor registers". They don't have addresses in the system memory space and can be accessed only by specific instructions.

The other is the registers that can control various hardware blocks (peripherals), in the CPU itself or external to it. On LPC1768 and many other embedded processors they're typically memory-mapped, and that's why they have addresses. For example the UART0 block is at address 0x4000C000 and that's where you need to read or write to communicate with it. To distinguish from the core registers, they can be called "peripheral registers" or "hardware registers".

On some low-end 8-bit microcontrollers like 8051 or PIC, there may be no core registers at all besides perhaps an accumulator, and all other registers are mapped into various memory areas like "internal RAM" (for temporary storage/calculation) or "Special Function Registers" (SFR) memory for the control and peripheral registers. In them, "registers" almost always have an address.

Bigger ARMs also have coprocessor registers, that can be used to control various core functions (e.g. MMU or cache) with instructions like MRC or MCR. These registers are similar to the core registers in that they don't have a memory address but just a number.

Also, on x86 you can have I/O ports, accessed by instructions in and out, which can be used to control some hardware blocks. These are similar in function to the peripheral registers but are usually not called such.

• Are the processor registers accessible in any way? – chevestong Mar 9 '13 at 4:29
• @ProSteve037: of course, otherwise there would be no point in having them :) Usuaully most instructions actually work with processor registers. E.g. on ARM: MOV, LDR, STR, ADD, SUB and so on. – Igor Skochinsky Mar 9 '13 at 16:57
• @ProSteve037 In a sense, processor registers do have a sort of address, but it is used in the register field of the opcode (the machine-code instruction-word), and cannot be confused with memory addresses (their positions in the opcode format are distinct, and the fields are different sizes). – luser droog Jul 20 '13 at 4:53

You are correct that some registers are not located inside the main memory, but rather in the microprocessor itself, and that those registers are memory-mapped into certain locations.

The LPC1768 microcontroller has only 64kB of RAM (what I believe you mean by main memory) however a 32-bit address bus and 4GB of total address space. The rest of this address space contains the flash memory storing your program, and the registers for all the peripherals (for example the output pin states, or the ADC).

Typically when you attempt to access a memory-mapped location, logic inside the microcontroller will identify where the memory address is physically located, and will operate control lines so the data gets to where it was intended, regardless of whether it is in RAM, a GPIO port or a peripheral control register.

This simplifies writing software, as you don't need to worry too much about where the registers are physically located, and makes compiling higher-level languages (like C) much easier.

In the specific case of the LPC1768, looking at the datasheet (http://www.nxp.com/documents/data_sheet/LPC1769_68_67_66_65_64_63.pdf) we can see the address map on page 20 (Figure 4), which shows where all the peripherals are mapped to in memory.

Of course, the processor also contains a handful of internal registers which are not memory mapped, these can be accessed much more quickly than anything in the address space, as the memory-management logic is slow compared to the core and are used as temporary storage during operations. Part of the job of a compiler is to handle storing data in registers and moving it out of/into memory for you.

As others have said, it depends on the microcontroller family. And it depends on what you mean by register.

The msp430 for example, has two sets of "registers". The first is the RISC register file, with 16 16bit registers. These include the Program Counter, Stack Pointer, Status, and Constant Generator registers, and 12 general use ones. These are registers in the traditional architecture use of the word.

The second set of registers are everything else. Ports, peripherals, interrupts, etc. These are part of the single memory file, and shares space with the general use RAM and Flash (Code Space)

For example the msp430g2231 has a Port 1 Output register at memory address 0x21.

You can access the register with register name p1out, but that's just a pointer to 8-bit memory address 0x21. Most importantly, that's how the compiler sees it. The header file, in this case msp430g2231.h, defines "p1out" as meaning 0x0021. Aside from the RISC register file, the common use of Register just means a memory address for x specific option. What you see as Register p1out, is just the way a higher language makes it easier for you to program, instead of memorizing memory maps.

As a generic term "register" just means a place where you can store ("register") information, nothing more.

Most architectures reserve the term register for locations within the CPU that are identified by bits in an instruction, and which are often accessible much faster than general bulk ("RAM") memory. (And often 2 or 3 registers can be accessed in parallel in one execution cycle.)

However, Microchip PIC documentation for instance, refers to all addressable locations as registers, even including RAM. When your professor copies this use of the term he should IMO inform you that this is not the way the term "register" commonly used nowadays. (Like I hope I did in my PIC assembler classes.)

• Not just microchip - look at the 8051 for a much earlier example, and even that may well have predecessors. – Chris Stratton Mar 8 '13 at 13:13
• @ChrisStratton: I'm pretty sure the General Instruments PIC (upon which Microchip's 16C54 was based) predates the 8051, and it might even predate its predecessor the 8048. – supercat Mar 8 '13 at 21:08
• Yes, it looks like it precedes the 8048 by around a year. – Chris Stratton Mar 9 '13 at 17:03

Registers do have addresses, even though they don't generally reside in memory.

Think about it a minute : an address denotes a location in some space, where memory is just one instance of a space. I/O often has its own address space; in some microcontroller architectures, code memory and data memory are separate spaces.

And so registers may have their own space too : sometimes FP and integer registers (and on the 68000 I believe, address registers) each have their own separate space.

One question is: how do we tell whether address 1 refers to byte 1 in memory, I/O port 1, or register 1? Usually from the context : in an IN or OUT instruction, obviously a port. In a register-to-register instruction, it's a register address. In a Load instruction, there will be a (big) memory address and a (small) register address, and so on.

In an ARM core, a memory address will usually be a 32-bit number; a register address will be a 5 bit number.

• Many processors have some registers which are accessed "by number", but also some registers that are only accessible using special instructions. I don't know how one could meaningfully describe the 6502's "S" register as having an address, for example. Aside from push/pop/call/return, the only instructions that access it are TSX/TXS (transfer S to X, or X to S). Bit 4 of the opcode selects between TSX and TAX, or between TXS and TXA, but it doesn't make sense to regard the opcodes as "Transfer X to register #b", since no other instructions refer to A is reg #0 and S as reg #1. – supercat Dec 5 '13 at 23:41

If one defines an address as being a set of k bits which may be used to select one item from a set of up to 2^k items, then it is common for many registers in many processors and controllers to have addresses, but also for controllers to have some registers which are strobed by circuits which detect particular conditions, and are not identifiable via any form of address. It's important to note, however, that in many cases the address wires which control CPU registers will have no relation to the address wires which are connected to larger memory systems. As such, register "addresses" will often exist in an entirely separate "universe" from memory addresses.

On most processors, register "addresses" are always either generated internally by the processor logic, outside the programmer's control, or fetched from certain bits in each instruction. The only way by change code could under software affect which register should be fetched by a particular instruction would be to patch the appropriate bits within that instruction. On the General Instruments PIC, whose design lives on in the form of the Microchip PIC, if an opcode specified all zeroes for an address, hardware would substitute the contents of a different register located at address 3. This allows code to use computations to select an address.

Perhaps the most important thing to understand about addresses is that it is possible for a system to have different address spaces that effectively exist in different universes. On the 8051, for example, there are, depending upon how one counts, at least four different address spaces and possibly as many as six; four of them are entirely independent (the instructions:

mov a,80h  ; Direct address space
mov a,@r0  ; Assume R0 = 80h
movc a,@a+dptr ; Assume A = 0 and DPTR = 80h
movx a,@dptr ; Assume DPTR = 80h


all retrieve data from "address 80h" but they read four unrelated things: an address in I/O space (the port 0 data register I think), internal data register 80h, code memory at address 0x0080, and external data memory at address 0x0080. In many systems, these things would in fact have no relation whatsoever to each other. The fact that a register will respond to a particular address in one universe says little or nothing about whether it will respond to that or any other address in a different universe.

RISC means "Reduced Instruction Set Computer". Part of the way you reduce the size of the instruction set is by having only one kind of data location, which includes Registers, RAM or I/O.

Back when people took these ideas seriously, the two expected advantages of RISC designs were, that you could make the processor much faster if you made it much simpler, and that you could optimize your program code if you could use any memory address for anything, instead of forcing everything to load and unload going through the ALU register for arithmetic, the Memory Address register for memory addressing etc.

Two remnants of that way of thinking are, (1) We have processors that PRETEND all registers are equal, by mapping registers into the memory space, and (2) We have professors that PRETEND all registers are equal, by calling registers memory locations.

Be tolerant. It was an important area of research for PHD students, which had a significant and lasting impact on the way some processors were designed.

• No. RISC does not tend to mean loss of distinction between the register file and main memory, as that would complicate instruction decoding, which is the opposite of RISC goals. RISC is classically about simple instructions which do what they do quickly, and leaving the programmer/compiler to string them together. So register and memory address versions of instructions have different encodings in a classic RISC architecture. And memory access is usually to an address provided by a register with a limited immediate displacement since only so many bits are available in the instruction word. – Chris Stratton Mar 8 '13 at 13:22
• You got that correct except the first sentence. Loss of distinction between register file and main memory is one of the ways classic RISC simplified instruction decoding, which is one of the goals of RISC. In practice, practical considerations intervene. For example see The Ultimate RISC – david Mar 13 '13 at 0:09
• A RISC instruction word quite explicitly codes a register number or a memory reference, which is a preservation of distinction compared to the situation contemplated here in which a register is coded exactly the same way as a memory address. – Chris Stratton Mar 13 '13 at 1:13
• Please read the reference first. Before posting. – david Mar 13 '13 at 2:42
• The reference is to an oddball academic architecture, not classic risc designs as actually built. – Chris Stratton Mar 13 '13 at 11:18

The 8051 if I remember right you could access the registers using memory addresses, but this is not the general case for all processors. The ARM processors have no way to do this, the general purpose registers r0-r15 cannot be accessed on the memory bus.