1 / 14100%
COMP 222: Computer Organization and Assembly Language
Extended Study Notes: Memory Addressing: Fundamentals and Applications
Student: Amber
Course: COMP 222
Institution: California State University, Northridge (CSUN)
Date: November 20, 2025
I. Learning Insights
My initial perception of a "memory address" was merely a sequential number, a
simple index in an array of bytes. However, studying computer organization has
revealed that memory addressing is the single most critical bridge between the
logical world of software and the physical constraints of hardware. It is the language
used by the CPU to negotiate with the memory subsystem (cache, RAM, and
eventually storage).
The true complexity lies not just in the address itself, but in the multiple layers of
abstraction applied to it. We dont just deal with a single, absolute physical address;
we deal with logical addresses, virtual addresses, segment offsets, and page
numbers. The application of addressing is a grand application of the Principle of
Locality (temporal and spatial) and Indirection (the foundation of virtual memory).
My most significant realization is the architectural trade-off embedded in
addressing: performance versus flexibility. For instance, requiring strict data
alignment (a hardware constraint) simplifies memory access logic and allows for
fast, single-cycle loads, thus prioritizing performance. Conversely, using complex
addressing modes like scaled-indexed addressing provides compilers with
maximum flexibility to generate efficient code for data structures like arrays, but at
the cost of significantly increased decoder complexity and potential multi-cycle
execution. The difference between a simple RISC load instruction and a complex x86
load instruction is fundamentally a debate over how much intelligence (and
complexity) should be encoded in the memory address calculation phase.
Ultimately, mastering memory addressing is synonymous with understanding the
limits, capabilities, and design philosophy of a CPU.
II. Knowledge Consolidation
A. Core Definitions and Address Spaces
1. Definition of Memory Address
A memory address is a unique identifier assigned to a specific location in a
computers memory. This location typically holds a single unit of storage.
2. Byte-Addressable vs. Word-Addressable Memory
Modern computer systems almost universally employ byte-addressable memory.
This means:
Every single byte (8 bits) in the memory system has its own unique, sequential
address.
If a system has (N) address lines, it can address (2^N) bytes of memory. For
example, a 32-bit address space can address (2^{32}) bytes, or 4 Gigabytes (GB) of
memory.
The addresses increment by 1 for each successive byte.
In contrast, word-addressable memory systems (now rare in general-purpose
computing) assign a unique address only to a word (e.g., 4 bytes or 8 bytes) rather
than every byte. The addresses would increment by the size of the word (e.g., by 4
for a 32-bit word).
The application of byte-addressing is granularity and flexibility, allowing individual
characters or small data types to be accessed directly, which is crucial for string
processing and peripheral communication.
3. Address Space (Logical vs. Physical)
It is critical to distinguish between the conceptual and physical representations of
an address:
Logical Address (or Virtual Address): The address generated by the CPUs execution
unit and visible to the program. In modern systems, this is the address space
managed by the operating system (OS) and the Memory Management Unit (MMU).
The size of the logical address space is determined by the register and instruction
set width (e.g., 32-bit or 64-bit addresses).
Physical Address: The address used by the memory controller to select the actual
physical memory chips (RAM). The size of the physical address space is limited by
the actual amount of installed RAM and the physical addressing capabilities of the
memory controller hardware.
The MMUs application is to translate the large, contiguous Virtual Address Space
into the actual, potentially fragmented Physical Address Space.
B. Endianness: The Ordering of Bytes
Endianness refers to the order in which multi-byte data words (e.g., 32-bit integers,
64-bit floating-point numbers) are stored in memory. The difference is based on
where the most significant byte (MSB) or the least significant byte (LSB) is placed in
memory relative to the words starting address.
1. Little Endian (LE)
The Least Significant Byte (LSB) is stored at the lowest (first) memory address.
Example: The 32-bit integer (0x12345678) stored at address (1000).
Address (1000): (78) (LSB)
Address (1001): (56)
Address (1002): (34)
Address (1003): (12) (MSB)
Application: Found in x86 architectures (Intel/AMD). It simplifies the retrieval of
data that requires truncation (e.g., reading a 16-bit value from a 32-bit address, as
the LSBs are already at the lowest address).
2. Big Endian (BE)
The Most Significant Byte (MSB) is stored at the lowest (first) memory address.
Example: The 32-bit integer (0x12345678) stored at address (1000).
Address (1000): (12) (MSB)
Address (1001): (34)
Address (1002): (56)
Address (1003): (78) (LSB)
Application: Traditionally found in network protocols (Network Byte Order) and
historically in architectures like Motorola 68k and IBM PowerPC. It aligns more
intuitively with human reading order.
Endianness is a crucial application of addressing when dealing with data transfer
across heterogeneous networks or systems, often requiring byte-swapping
operations.
C. Data Alignment and Performance
Data alignment is a hardware constraint that mandates multi-byte data types (like
16-bit half-words, 32-bit words, or 64-bit double-words) must start at a memory
address that is a multiple of their size.
1. Alignment Requirement
For a data type of size (S) bytes, it must be stored at an address (A) such that:
A mod S=0
Example: A 32-bit word (4 bytes) must start at an address that is a multiple of 4
(e.g., (0, 4, 8, 12, ...)).
2. Performance Implications
The application of alignment is pure performance optimization. Memory is typically
accessed in units equal to the CPUs bus width (e.g., 4 bytes or 8 bytes).
Aligned Access: If a word starts at a multiple-of-four address, the entire word can be
fetched from the memory controller in a single, efficient access cycle. The address
request aligns perfectly with the memory bank boundaries.
Misaligned Access: If a 4-byte word starts at an address like (1001), the access spans
two separate, adjacent memory words in the physical memory system (e.g., part of
the word at addresses (1000-1003) and the rest at (1004-1007)). This requires the
CPU to:
Perform two separate memory accesses.
Shift and merge the data internally.
This process introduces significant latency (often 2-4 extra cycles) and control logic
complexity.
RISC architectures (like MIPS) often enforce strict alignment and generate a
hardware exception (trap) on misalignment to enforce high performance. CISC
architectures (like x86) often allow misaligned access but suffer the performance
penalty in the hardware unit that handles the address translation.
D. Addressing Modes in Instruction Sets
Addressing modes define how the CPU calculates the Effective Address (EA) of an
operand (the final memory address used for access). The instruction encoding
dictates which modes are supported and how their parameters are represented.
Mode
Calculation of Effective Address (EA)
Application Scenario
Immediate
(EA = \text{Instruction Word}) (Operand is the value itself, no memory access)
Loading constants directly into registers (e.g., addi
t0,
zero, 100).
Register
(EA = \text{Register Value}) (Operand is in a register, no memory access)
Arithmetic and logical operations (e.g., add
t0,
t1, $t2).
Direct (Absolute)
(EA = \text{Address Field Value}) (The address is given explicitly in the instruction)
Accessing global variables or known, fixed memory locations.
Register Indirect
(EA = \text{Register Value}) (The register holds the address of the operand)
Implementing pointers and dynamically accessing data structures (e.g., linked lists).
Base + Displacement
(EA = \text{Base Register} + \text{Offset/Immediate})
Most common mode for arrays, structs, and stack variables (e.g., lw
t0,16 ¿
sp)).
PC-Relative
(EA = \text{PC}_{\text{next}} + \text{Offset/Immediate})
Conditional branches and jumps, enabling Position-Independent Code (PIC).
The choice of addressing modes is an application of compiler optimization. Richer
modes (like Base + Displacement) allow the compiler to generate fewer instructions
to access complex data structures.
E. Virtual Memory and Address Translation
The most sophisticated application of memory addressing is Virtual Memory,
managed by the OS and MMU. It provides three critical services:
Isolation: Separating the address space of one process from others, ensuring
security and stability.
Multitasking: Allowing multiple processes to concurrently use memory that appears
to be contiguous and large.
Memory Management: Allowing a program to run even if only parts of it are
currently loaded into physical RAM (demand paging).
1. Paging Fundamentals
The virtual address space is divided into fixed-size units called Pages (e.g., 4 KB).
The physical address space is divided into identically sized units called Frames.
The Virtual Address (VA) is divided into two main components:
VA=Page Number Page Offset
Page Offset: The lower bits of the VA, which specify the location within the
page/frame. Its size is determined by the page size ((\lceil \log_2(\text{Page
Size}) \rceil) bits). This part is not translated.
Page Number: The upper bits of the VA, which are used as an index into a data
structure called the Page Table.
2. Address Translation Process
The MMU uses the Page Number to look up the corresponding Frame Number in the
Page Table. The Physical Address (PA) is then constructed by substituting the Page
Number with the Frame Number:
PA=Frame Number Page Offset
The application of this translation is security and memory abstraction. The Page
Table mapping changes for every process, ensuring that two different processes
accessing the same virtual address (e.g., 0x1000) are mapped to two entirely
different physical memory locations.
3. Translation Lookaside Buffer (TLB)
Because every memory access potentially requires two physical memory accesses
(one for the Page Table lookup and one for the actual data), a hardware cache called
the Translation Lookaside Buffer (TLB) is used. The TLB caches recent VA-to-PA
translations, leveraging temporal locality to significantly accelerate the translation
process.
III. Example Problems and Analysis
Problem 1: Byte Addressing, Alignment, and Endianness
A 32-bit architecture is byte-addressable and little-endian. A program attempts to
load a 32-bit integer (a word) with the hex value (0x\text{AABBCCDD}) into
memory starting at address (0x2003).
(a) What is the alignment status of this memory access?
(b) If the CPU allows the misaligned access, what value is stored at memory address
(0x2005)?
(c) If the CPU enforces strict alignment, which four addresses are valid start
addresses immediately following the address (0x2000)?
Analysis and Solution
(a) Alignment Status:
The data size is 4 bytes (a 32-bit word).
The starting address is (A = 0x2003).
The alignment condition is (A \mod 4 = 0).
0x2003 mod 4=3
Since the remainder is 3 (not 0), the access is misaligned.
(b) Value at Address (0x2005) (Little-Endian):
The architecture is Little Endian (LSB at the lowest address).
The word is (0x\text{AABBCCDD}).
LSB: (DD)
Byte 2: (CC)
Byte 3: (BB)
MSB: (AA)
Since the starting address is (0x2003), the bytes are stored as follows:
Address Content (Hex) Byte Significance
(0x2003
)
(DD) LSB
(0x2004
)
(CC)
(0x2005
)
(BB)
(0x2006
)
(AA) MSB
Therefore, the value stored at memory address (0x2005) is (BB).
(c) Valid Aligned Addresses:
For a 4-byte word, the addresses must be multiples of 4.
The address (0x2000) is valid ((0x2000 \mod 4 = 0)).
The next four valid addresses are found by repeatedly adding 4 ((0x4)):
(0x2000 + 0x4 = 0x2004)
(0x2004 + 0x4 = 0x2008)
(0x2008 + 0x4 = 0x200C)
(0x200C + 0x4 = 0x2010)
The valid aligned start addresses are (0x2004, 0x2008, 0x200C, 0x2010). The
application of alignment ensures that the memory access is always performed
optimally, requiring only one fetch cycle.
Problem 2: Base + Displacement Addressing Mode (MIPS Context)
Consider a MIPS-like architecture with a 32-bit address space, where registers are
32 bits wide. An array of 64-bit double-words is stored in memory. The base
address of the array (the address of the first element, index 0) is stored in register (
s1¿,andthedesiredindex (i)isstoredinregister¿
t0). The instruction set only supports
the Base + Displacement addressing mode, where the displacement is a 16-bit
signed immediate.
(a) Write the sequence of MIPS instructions necessary to calculate the memory
address of the element at index (i) and store it in register ($t1).
(b) Explain why the Base + Displacement addressing mode, despite being
constrained by a 16-bit offset, is the most frequently used mode for accessing stack
variables and local arrays.
Analysis and Solution
(a) Instruction Sequence:
Since the array holds 64-bit double-words (8 bytes), the offset must be (i \times 8).
MIPS cannot directly multiply registers by 8, but we can achieve this with a left shift.
sll
t0, 3: Shift register ($t0) (index (i)) left by 3 bits. This multiplies the index by
(2^3 = 8), calculating the byte offset.
\text{Offset} = i \times 8
add
s1,
t1 : Addthebaseaddress ¿
s1)) to the calculated byte offset (in ($t1)). This
calculates the Effective Address (EA) of the element at index (i).
\text{EA} = \text{Base} + \text{Offset}
The sequence:
sll
t0, 3 #
t1=¿
t0 * 8 (Calculates byte offset)
add
s1, t1 # t1 =
s1+¿
t1 (Calculates Effective Address)
(b) Application Rationale:
The Base + Displacement mode is heavily used for two reasons, leveraging the 16-
bit immediate constraint:
Stack Variables: Local variables are accessed relative to the stack pointer ((
sp ¿¿orframepointer ¿
fp)). The displacement is the fixed, known offset of the variable
from the base pointer. Since a functions local storage frame is typically much
smaller than
64 KB
(the range of the 16-bit offset), this mode perfectly encapsulates
the access in a single, efficient instruction (e.g., lw
t0,12 ¿
sp)).
Array/Struct Access: This mode naturally supports accessing fields within a struct
or elements within an array when the index is a small constant (the displacement)
relative to the arrays base address. Even when the index is a variable (as in part a),
the combination of address calculation (shift and add) results in a highly optimized
instruction count for one of the most frequent memory operations in compiled code.
The application is a perfect example of optimizing for the common case where local
memory access dominates.
Problem 3: Virtual to Physical Address Translation (Paging)
A system uses a 32-bit virtual address space and a 20-bit physical address space.
The page size is (4 \text{ KB}).
(a) Determine the size of the Page Offset and the Page Number fields in the Virtual
Address (VA).
(b) Given the Page Table Entry (PTE) for Virtual Page Number (VPN) 0x3045 is
0x0C3 and the virtual address being accessed is (0x30454321), calculate the
corresponding Physical Address (PA). Assume the VPN/Frame Number are in
hexadecimal.
(c) Describe the application of the Page Offset field during the address translation
process.
Analysis and Solution
(a) Page Offset and Page Number Size:
Page Size to Offset: The page size is (4 \text{ KB} = 4096 \text{ bytes}).
\text{Offset Bits} = \log_2(4096) = 12 \text{ bits}
Page Number Size: The VA is 32 bits.
\text{Page Number Bits} = 32 \text{ bits} - 12 \text{ bits} = 20 \text{ bits}
The VA structure is: 20-bit Page Number
12-bit Page Offset.
(b) Physical Address Calculation:
Extract Components from VA:
\text{VA} = 0x30454321 \quad (\text{32 bits})
Page Offset: The lower 12 bits (3 hex digits): (0x321).
Virtual Page Number (VPN): The upper 20 bits (5 hex digits): (0x30454).
Page Table Lookup:
The problem provides the lookup result:
PTE for VPN 0 x30454
is
0x0C3
.
(Assuming the problem meant VPN
0x30454
based on VA structure).
\text{Frame Number} = 0x0C3 \quad (\text{Note: This is an 8-bit Frame Number,
which is small for a 20-bit PA space, but we proceed with the given value.)}
Since the PA is 20 bits and the offset is 12 bits, the Frame Number must be (20 - 12 =
8) bits. The given value (0x0C3) is (12) bits, lets assume the question meant a 12-bit
frame number, which leaves
20 12=8
bit frame number. The PA is 20 bits, and the
offset is 12 bits. The Frame Number (FN) is (20-12=8) bits. Lets assume the Frame
Number is
0xC3
(8 bits).
PA=Frame Number Page Offset
Frame Number (FN)=0x0C3
(Assuming this is the FN, padded to 8 bits for 20-bit PA
space:
0xC3
)
Page Offset=0x321
Construct PA:
The PA is 20 bits total. The FN is 8 bits and the Offset is 12 bits.
\text{PA} = 0x\text{C3} \parallel 0x321 = 0x\text{C3321}
The corresponding Physical Address is (0x\text{C3321}).
(c) Application of Page Offset:
The application of the Page Offset field is its invariance during translation. It serves
as the physical displacement within the frame, exactly as it was the virtual
displacement within the page. The MMU does not translate, modify, or consult the
Page Offset; it simply appends it to the newly found Frame Number. This design
choice simplifies the translation hardware and ensures that the relative ordering of
data within a page is preserved in the corresponding frame in physical memory.
Problem 4: Micro-Architectural Impact of Misalignment
Explain in detail the micro-architectural consequences of allowing misaligned
memory access (as commonly permitted in x86 CISC architectures) versus strictly
enforcing alignment (as in MIPS RISC architectures), specifically focusing on cache
and bus operations for a 64-bit word access on a 64-bit bus.
Analysis and Solution
The micro-architectural consequence is a direct trade-off between hardware
simplicity (MIPS) and programmer flexibility (x86).
MIPS (Strict Alignment)
Enforcement: The hardware checks if the address (A) satisfies
A mod 8=0
for a 64-
bit load.
Aligned Access:
The address request perfectly maps to a single 64-bit cache line/word boundary.
The memory controller receives one request and returns the 64 bits in one bus
cycle.
Consequence: Single memory access, simplified load/store unit, maximum
performance.
Misaligned Access:
The hardware detects the misalignment and immediately raises a precise exception
(trap/interrupt).
Consequence: The instruction is terminated, forcing the OS exception handler to
deal with the error. This strictly enforces the high-performance path and delegates
complex boundary handling to software, keeping the CPU core fast and simple.
x86 (Permissive Misalignment)
Enforcement: The hardware is designed to handle misalignment. No exception is
generated by default.
Misaligned Access (Worst Case: Boundary Crossing):
Consider a 64-bit load starting at address (0x...07). This load spans the 64-bit
memory word starting at (0x...00) and the next 64-bit word starting at (0x...08).
Consequence 1: Multiple Cache/Bus Accesses: The hardware must split the single
logical load into two separate physical bus transactions.
Transaction 1: Accesses the first memory word (from
0x.. .00
to
0x.. .07
) to retrieve
the 1 byte starting at
0x.. .07
.
Transaction 2: Accesses the second memory word (from
0x.. .08
to
0x.. .0 F
) to
retrieve the remaining 7 bytes.
Consequence 2: Data Manipulation Overhead: The Load/Store Unit (LSU) must then
include complex internal shift registers and merge logic to combine the two 64-bit
chunks of data fetched from memory into the single, correctly byte-ordered 64-bit
result for the destination register.
Performance Penalty: The effective load latency is significantly increased (often
doubling or tripling the cycle count) due to the need for multiple bus transactions
and the subsequent merging overhead.
Summary of Application Trade-off: The MIPS approach is an application of design
simplicity and performance purity, where the burden of alignment is placed on the
compiler/programmer. The x86 approach is an application of architectural
tolerance and programmer convenience, where the massive complexity of handling
all possible byte boundary crossings is permanently built into the silicon (the LSU).
The cost is sustained complexity and a guaranteed performance degradation for all
misaligned memory accesses. The total transistor count and power budget for the
x86 memory subsystem is exponentially higher due to this permissive addressing
application.
Problem 5: Stack and Heap Addressing
The stack and heap are two fundamental areas of memory used during program
execution, each relying on distinct addressing strategies. Explain the addressing
application differences between the stack and the heap.
Analysis and Solution
The difference between stack and heap addressing is a primary application of
runtime memory organization and pointer management.
Feature
Stack Addressing Application
Heap Addressing Application
Data Type
Local variables, function parameters, return addresses.
Dynamically allocated data (e.g., objects, large arrays) whose size is unknown at
compile time.
Structure
LIFO (Last-In, First-Out). Contiguous and highly predictable.
Unstructured, fragmented, and managed via complex data structures (free lists,
bitmaps).
Primary Addressing Mode
Base + Displacement (e.g., lw
t0,8¿
sp)). The Stack Pointer ((
sp ¿¿orFramePointer ¿
fp)) acts as the Base, and the variables location is a small, fixed offset
(Displacement).
Register Indirect or Register + Displacement. Access is always through a register
containing the base pointer (the address returned by malloc/new).
Address Calculation
Fast and Simple. Offsets are fixed constants determined by the compiler (known
before runtime). Calculation is a single-cycle register addition.
Complex and Indirect. Requires two stages: 1. Fetching the heap pointer from a local
variable/register. 2. Using that pointer (Base) to access the data. Requires
management of indirection.
Contiguity/Locality
Excellent Spatial and Temporal Locality. Addresses are tightly packed and accessed
sequentially in function calls/returns. This optimizes L1/L2 cache usage.
Poor Locality. Due to fragmentation and dynamic allocation, heap addresses can be
scattered across the physical address space. Access often results in cache misses.
Management
Hardware/Compiler Managed. The address space is automatically managed by
decrementing/incrementing the (
sp ¿¿
sp, $sp, -16).
Software Managed (Allocator). Relies on complex runtime algorithms (e.g., free(),
delete) to track and reclaim addresses, leading to overhead and potential memory
leaks.
The application of stack addressing prioritizes speed and predictability by using the
simple Base + Displacement mode. The application of heap addressing prioritizes
flexibility and scalability by relying on dynamic pointer management, accepting the
inherent cost of slower access and potential memory fragmentation.
IV. Comprehensive Conclusion
Memory addressing is far more than a simple counting system; it is the central
organizing principle of computer architecture. The entire performance envelope of a
CPU is defined by how effectively it can calculate and translate addresses.
We have detailed the fundamental distinction between byte-addressing (ubiquitous
for its granularity) and word-addressing. The concepts of Endianness (a data
ordering application) and Data Alignment (a performance optimization application)
illustrate the critical constraints imposed on the address space by hardware design
to ensure maximum throughput. Misalignment, for instance, perfectly demonstrates
the trade-off: allowing it (CISC) increases programmer freedom but cripples the
memory units speed; enforcing it (RISC) ensures single-cycle access speed at all
costs.
Furthermore, the variety of Addressing Modes reveals the application of encoding
for compiler efficiency, allowing high-level data structures to be mapped to optimal
instruction forms (e.g., Base + Displacement for arrays).
Finally, the most powerful application is Virtual Memory, which utilizes address
translation (Page Number
Frame Number) to provide critical security, isolation,
and memory abstraction. The complexity of this translation, mitigated by the high-
speed TLB, is the price paid for modern multitasking operating systems.
The study of memory addressing in COMP 222 moves us from seeing a number to
understanding a complex, layered negotiation between the softwares needs for a
large, contiguous address space and the hardwares constraints of fragmented
physical memory and the need for speed. All performance bottlenecks in modern
computing often trace back to an inefficient address calculation or an expensive
address translation.
Students also viewed