Physical Memory
Modern computers rely on program instructions and data being stored in 'physical memory', which is addressable using discrete integers. Memory addresses are often represented in hexidecimal notation, e.g., "0x10AEDDE3". As each hexidecimal character is encoded in 4 bits, a 32 bit address can be represented using 8 hexidecimal characters. Using 32 bit addresses, a program can access about ~4 billion different memory locations (2^32 = 4,294,967,296).
Typically, each memory location refers to some number of contiguous bits. For example, when using the MIPS architecture, each address refers to a single byte of memory - 8 bits. However, as the MIPS architecture is a 32 bit architecture, most often addreses are used that are a multiple of 4, and these refer to a group of 4 bytes (see Table 1).
In order to have enough memory to accommodate a 32 bit address space, you would need 4 Gigabytes of memory. Although common now, when 32 bit processers were first available, it is unlikely that even the most expensive computers would have contained that amount of physical memory. Similarly, now that we have 64 bit processors, a computer would need 18 billion Gigabytes of memory to accommodate the entire address space (see Table 2).
Another problem is that generally as most programs execute the amount of memory they use increases. In particuarly, as most programming languages use a call stack to store state information between function calls, this stack structure usually grows within a contiguous section of memory. If programs are directly accessing physical memory this stack might grow to the point where it is interferring with the memory of other programs.
Due to these problems, early computers could only run one program at a time, and only conventions regarding the use of memory would limit interference between a program and the areas of memory reserved for the operating system. Later, similar conventions, allowed cooperative multi-tasking systems such as the early versions of Mac OS and Windows to run multiple programs at the same time, but due to lack of memory separation between programs these were prone to either crashing due to incorrect memory access, or hanging (freezing) due to a program entering and infinite loop or becoming dead-locked on a resource request and thus prevented from handing back control to the operating system.
It was only when IBM's OS/2 and Windows 95 were released that operating systems began to take advantage of the memory protection functionality provided by the processors of the day. Since then, while most CPUs provide a 'real' mode that allows a program to directly access physically memory, modern personal computers operate in what is often referred to as 'protected' mode. This allows an operating system kernal, which is a program that runs with increased privileges, to set up a memory mapping between a 'virtual address spaces' for each program and physical memory.
Table 1. | |
Address | Value stored at address |
---|---|
32 bit address | 32 bit value |
0x0000 0000 | 0000 1001 1010 0000 0000 0000 0000 0000 |
0x0000 0004 | 0000 1010 1010 0000 0000 0000 0000 0000 |
0x0000 0008 | 0000 1001 0010 0000 0000 0000 0001 0000 |
... | |
0xFFFF FFF0 | 0000 1001 0010 0000 0000 0000 0001 0000 |
0xFFFF FFF4 | 0000 1001 0010 0000 0000 0000 0001 0000 |
0xFFFF FFF8 | 0000 1001 0010 0000 0000 0000 0001 0000 |
0xFFFF FFFC | 0000 1001 0010 0000 0000 0000 0001 0000 |
Table 2. | ||
Architecture | # addresses | Addressable memory |
---|---|---|
8 bit | 256 | 256 B |
16 bit | 65,536 | 64 KB |
32 bit | 4,294,967,296 | 4 GB |
64 bit | 18,446,744,073,709,551,616 | 18,446,744,073 GB |
References