New to OS - Segment and Disk BootSector

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
FelixGB
Posts: 2
Joined: Tue Apr 21, 2020 6:51 am

New to OS - Segment and Disk BootSector

Post by FelixGB »

Hi everyone,

Hope you are all doing good with the current worldwide situation!

While being at home, I decided to challenge myself and learn something completely out of my comfort zone.
I followed some tutorial, read a lot and played with my own .asm program and even an bootsector / qemu.
I did learn a lot so far, but also a lot about gdb and how to run it to debug my project.

I am currently reading through this PDF and this Github Project that seems to be following the PDF. I also use a lot OSDev wiki for various references.

My first question is regarding the segment
I went trough the OSDev Segmentation page.
I do not understand this :

Code: Select all

Eg, the segment 0x1000 has a base address of 0x10000. This segment occupies the physical address range 0x10000 -> 0x1FFFF, However the segment 0x1010 has a base address of 0x10100. This segment occupies the physical address range 0x10100 -> 0x200FF
Why does 0x1000 has a base address of 0x10000?
Where is that extra 0 coming from?
Ain't we in 16bit mode at this point?


My second question is regarding the Disk BootSector
I pretty much understand the code from this example along with the referenced url.
The only thing that I do not understand about that example, is while using Qemu (-s -S) to run my bin file and using gdb to check the registers values (b 0x7c00 -> c -> info registers dl), I can see that DL register is already set to 0x80.
Where is it coming from? I was expecting that I would have to set it myself in my asm file.
Is it because we "booted from hdisk" through Qemu and bootloader set dl to 0x80?

Thank you very much for the help!
Felix
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: New to OS - Segment and Disk BootSector

Post by BenLunt »

FelixGB wrote:Why does 0x1000 has a base address of 0x10000?
Where is that extra 0 coming from?
Ain't we in 16bit mode at this point?
Here is a question to answer your question.

If the registers are 16-bit, how do you address memory above the 16-bit limit of 65536? You can't.

Therefore, the designers decided to create a pair of registers to be able to access more memory. For example, these 16-bit machines could access up to 20 bits of memory, 1 Meg. So how did they do it?

Using segments on 16-byte boundaries. 16 bytes is called a "paragraph" of memory.

Now, using an index value, you can point to any one of these paragraphs. Since 0xFFFF is the largest number I can place in a 16-bit register, this means I can access 65536 paragraphs of memory. 65536 * 16 = 1 Meg.

Now I use two registers, the first to point to the paragraph wanted (this being my base address) and the second register as an offset from this base.

Code: Select all

Physical address = (paragraph index * 16) + offset
Now I can access any memory location between 0x00000 and 0xFFFFF using this method. (See below for an 'extra')

Example: Paragraph index of 0x1234 and an offset of 0x5678 points to physical address 0x179B8.

Code: Select all

Physical address = (0x1234 * 16) + 0x5678

   0x12340
  +0x05678
----------
   0x179B8
Do you see where the extra '0' comes from now? Any number times 16 is simply adding a zero to the right side (when using hex values of course).

Now for the 'extra' noted above. Since I can use a value of 0xFFFF in the paragraph index register *and* a value of 0xFFFF in the offset register, I can actually access more than 1 meg of RAM.

Code: Select all

   0xFFFF0
  +0x0FFFF
----------
  0x10FFEF
0x10FFEF = 1 Meg + 65,536 - 16 - 1. Therefore, I can access 1 Meg plus 64k minus 16 bytes of RAM using this method.

Now, back to the answer:
The paragraph index value must be placed in a segment register: CS, DS, ES, SS (FS and GS)
The offset value must be placed in a base/index register: BX, BP, SP, SI, DI, (IP).

Therefore, I can use a register pair of one of the segment registers and one of the offset registers to access any memory between 0x00000 and 0x10FFEF.

Segment register is the index value pointing to which paragraph I want to use as my base, and a base/index register used as an offset from that base.

Code: Select all

Physical address = (DS * 16) + BX
Does this make sense?

Ben
- http://www.fysnet.net/osdesign_book_series.htm
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: New to OS - Segment and Disk BootSector

Post by BenLunt »

FelixGB wrote:Where is it coming from? I was expecting that I would have to set it myself in my asm file.
Is it because we "booted from hdisk" through Qemu and bootloader set dl to 0x80?
When running your boot sector, you would like to be able to know which disk you are booting from, correct? For example, you are booting from the first hard drive, the firmware loaded the first sector of this hard drive and now you want to continue to load sectors from this hard drive.

How do you know which hard drive value (DL) to send to the firmware to continue loaded sectors?

The firmware, the Legacy BIOS in this case, will set the DL register to the value you need to use to continue loading sectors. This DL register is set just before the firmware jumps to your boot sector code. Therefore, you need to save this register as one of the first things you do.

The firmware will also set other registers to specific values just before it jumps to your boot sector, all depending on whether you have PnP devices, etc. However, DL is really the only one you need to worry about at this point in your development/learning experience.

As an additional note, since you previously asked about segments, let me make a few other notes about which registers the firmware will set, specifically the CS:IP register pair. The firmware will set the CS:IP register pair to point to physical address 0x07C00. However, it does not have to use any specific combination of CS:IP to point there as long as the two values, when combined, point to 0x07C00. (0x07C00 being the physical address the firmware loaded your boot sector to)

For example, the two common paired values are:

Code: Select all

  07C0:0000   and
  0000:7C00
However, any combination can be used as long as the result points to 0x07C00.

Code: Select all

  0682:13E0   and
  0111:6AF0
The firmware is not obligated to use the first two mentioned (though 99.99% will).

Here is one more thought to think about. As long as you don't access memory using the CS segment register--meaning direct jumps, CS override, etc.--you don't need to even worry about what the CS:IP register pair is. It could be one of the second example values I mention and it will still boot just fine.

Hope this helps. (Gives you a lot to think about, doesn't it?)

Ben
- http://www.fysnet.net/osdesign_book_series.htm
FelixGB
Posts: 2
Joined: Tue Apr 21, 2020 6:51 am

Re: New to OS - Segment and Disk BootSector

Post by FelixGB »

Hi Ben,

Thank you very much for your replies.

They were really helpful and really clear. I really like the way you explained.
I will play around with these 2 concepts to make sure everything is clear.

And as you said, it did give me a lot to think about!

Have a great day and stay safe!
Felix
Post Reply