In prior models, the space between stack and heap is not used, but takes up memory.
Segmentation allows the OS to place code, stack and heap in different parts of memory. →Note that the address space is NOT destroyed (it’s virtual, after all).
In this case, MMU needs 3 sets of base and bounds register pairs.
Segmentation Fault occurs when the address is beyond the bound of the current segment.

Explicit approach: use the top few bits to imply the referring segment. The other part is offset.
Implicit approach: the segment is decided by noticing how the address was formed.
This time, the register pair stores base address and size of the segmentation.
The problem is that the stack grows backwards (towards address 0). The hardware also need to know where the segment grows, or if it grows positive.
Solution: segment registers come with negative-growth mark.

For stack, physical address = base address - max segment size + offset
To support code sharing between address spaces, add a few protection bits per segment, indicating a program’s permissions on the segment.
Now the segment register be like:

(细粒度和粗粒度)
Dividing the address space into code, stack and heap is coarse-grained. Supporting more segments, a.k.a. fine-grained segmentation requires segment table in memory.
Fine-grained segmentation improves memory usage efficiency.
During context switch, the segment registers must be saved and restored.
In actual situations, physical memory is not a bunch of slots. External fragmentation may occur (see right). OS may rearrange the segments to free up space, but the operation costs a lot of processor time.
OS may also use free-list management algorithm, to keep large extents of memory for allocation. Algorithms are best-fit, worst-fit, first-fit, buddy algorithm and so on.
