Building an OS
#4 Segmented Memory Model
Remember we are in 16 bit mode. That means the size of every register is 16 bit only. So how much memory can we access using a 16-bit address?
2^16 = 65,536 Bytes
that’s only 64 KB.
But 64 KB was not sufficient as the complexity of the software grows the demand for memory also increased with it.
Intel solution to this was using a 20 bit address line instead of 16 bit. This would increase the memory accessible from 64 KB to 1 MB.
2^20 = 10,48,576
that would be 1 MB
.
How did Intel did that?
They introduced a new category of a register called segment register.
- DS (Data Segment)
- CS (Code Segment)
- SS (Stack Segment)
- ES
- FS
- GS
Side note: Among these CS always contains the segment currently code is executing and you can’t set it using MOV instruction. This register contains the segment address.
Now all the addresses are represented using a segment address pair like DS:DI where DS defines the start of the segment and the final address is calculated by adding both the address. Just one trick here. segement register(DS in this case)is left shifted by 4 bit before adding it to DI
- Orange area is the current segement.
- The number on the top and bottom of the segment is the start and end address of the segment.
- DS:DI arrow point the address within the segment.
- Two or more segments can overlap with each other.
- Images are not to scale
Calculate physical address
Let’s take the example of DS:DI. We would be using the below formula to calculate the physical address.
physical address = (DS * 0xF) + DI
Few more things about segment register
You can’t use any register with any segment register.
Segement | Offset registers | Description |
---|---|---|
CS | IP | Code pointer |
DS | BX, DI, SI | Data pointer |
SS | SP, BP | Stack pointer |
ES | BX, DI, SI | Used as destination address |
Time to revisit the hello world program!
Let’s now clear the segment address that I skipped in the previous post. Link to the post
(Image not to scale)
Our message Hello world
is present in the section highlighted using blue.
To access it we can follow two-approach either set segment register at 0 or set the segment register at 0x7C00
We’re going to cover both the approach.
When segment register is set to 0x0
First, we need to tell our assembler to calculate all the address from 0x7C00 using ORG command and set the offset register to start of our string address.
BITS 16
ORG 0x7C00
main:
MOV AX, 0
MOV DS, AX
MOV SI, msg
CALL print_string
msg DB "Hello World", 0
(Removed print_string and other bootstrap code for simplicity)
Can you guess, What is the address in the SI
register?
MOV SI, 0x7c16
MOV SI, 0x16
When segment register is set to 0x7C00
BITS 16
ORG 0
main:
MOV AX, 0x7C0
MOV DS, AX
MOV SI, msg
CALL print_string
msg DB "Hello World", 0
(Removed print_string and other bootstrap code for simplicity)
DS register is 0x7C0, not 0x7C00 because the segment register is left sift by 4 bit before added.