Code: Select all
org 0x7C00
Code: Select all
org 0x7C00
If I may, I would like to expand on the answers that have been given.abstractmath wrote:Also, how can I roll my own bootloader code within the MBR? Any clarification on these questions would be much appreciated, thanks!
I actually prefer to set CS to 7C0 instead (with a far jmp) so that org is not needed, and also so it works regardless of how the BIOS set up CS before jumping to the boot sector code.iansjack wrote:The org directive tells the assembler at what address the program will be loaded. This is important to ensure that any references to memory addresses are correct. Note that this means you should explicitly set the segment registers to 0 early in your code.
Code: Select all
BootSectInit:
jmp StartBoot
nop
db 'Rdos '
BootMedia boot_struc <>
StartBoot:
db 0EAh
dw OFFSET JmpBootCode
dw 07C0h
JmpBootCode:
I prefer to use the hidden sector count in the BPB to place the second stage boot loader directly after the MBR. When I partition a disc for my operating system, I always create a MBR with 16 hidden sectors and then the actual partitions will be after that. I have no nested booting, rather it's the second stage boot loader that scans the root partition (which always needs to be FAT12, FAT16 or FAT32) for OS image files, and then either loads the normal boot file on timeout or the one the user selects.BenLunt wrote:abstractmath wrote: Once you have a working MBR, and it can load the first sector of your partition, usually called a Partition Boot Record (PBR), you now need a valid PBR.
The PBR is specific to the file system it resides on. However, it needs a few notes:
1) The PBR needs some way to know where is resides--the base LBA of this partition. This is usually done with a BPB, like in the FAT file systems, for example.
2) It may need to load extra sectors since the 512 bytes your MBR loaded may not be enough. One huge mistake some newbies have made is to put their "read_from_disk" code in the sectors yet to be read. Your "read_from_disk" code *must* reside within the first 512 bytes, including any data it might need to do so.
3) This PBR will usually parse the file system to find a loader file. This may have a few requirements, such as the loader file must be in the root directory. However, if you feel ambitious enough, you can write your PBR to search sub directories as well.
This is definitely not true of USB flash drives. I've even seen one BIOS skip the MBR code entirely and go directly to loading the first sector of the active partition. (Unfortunately, it's not a convenient development machine, so I haven't checked to see if it will do that with the internal hard disk.)BenLunt wrote:The BIOS has absolutely no idea, nor does it care what the first sector of the disk is, other than if the sector has the correct Signature at offset 510. Some BIOSes also check the first few bytes of the sector for valid code, but this is not standard.
Most control flow instructions don't rely too much on the value of CS, so they work regardless of how the BIOS set up CS. But I'd still recommend setting the segment registers (including CS) to 0 and using org 0x7C00 so that address calculations can ignore segmentation.rdos wrote:I actually prefer to set CS to 7C0 instead (with a far jmp) so that org is not needed, and also so it works regardless of how the BIOS set up CS before jumping to the boot sector code.
You cannot use offsets if you don't know the CS (and IP).Octocontrabass wrote:Most control flow instructions don't rely too much on the value of CS, so they work regardless of how the BIOS set up CS. But I'd still recommend setting the segment registers (including CS) to 0 and using org 0x7C00 so that address calculations can ignore segmentation.rdos wrote:I actually prefer to set CS to 7C0 instead (with a far jmp) so that org is not needed, and also so it works regardless of how the BIOS set up CS before jumping to the boot sector code.
You cannot use absolute offsets, but IP-relative offsets still work fine as long as you stay within the boundaries of CS. It's safe to assume CS will be either 0 or 0x7C0 upon entry to your boot sector, so you can jump anywhere within the overlap between those two 64k segments using a relative jump (although it's still a good idea to set CS as soon as possible).rdos wrote:You cannot use offsets if you don't know the CS (and IP).
Personally, I don't.rdos wrote:Personally, I think segmentation is useful,
It's not a problem if you understand what it's doing and why. That's why we recommend being familiar with your toolchain.rdos wrote:and orgs are a bit problematic, especially if the linker/locator fills up with zeros.
But a DOS .com executable requires org 0x100.rdos wrote:It's a lot easier to create a binary image that starts at zero without having to rely on fancy tools. You can even create a dos .com executable.
Gotta disagree with you there too. Setting segment registers to zero is much more convenient.rdos wrote:Also, when the second stage boot-loader is loaded, it's most convenient to avoid orgs there too and place it at offset 0 in some fixed segment.
I agree with you, Octocontrabass. I in my bootloader was using segments in the second stage at one point. This made it nearly impossible to switch to PMode, as I had to deal with segments. I prefer zeroing everything, and then using flat segments in PMode or long mode. I think segmentation could be better, but it just needs some changes.Octocontrabass wrote:Gotta disagree with you there too. Setting segment registers to zero is much more convenient.
Actually, it's just as easy to load a code selector with a zero base as a non-zero base. If you load your second stage boot loader at a fixed segment, you can safely use a fixed base for the code segment in protected mode.nexos wrote:I agree with you, Octocontrabass. I in my bootloader was using segments in the second stage at one point. This made it nearly impossible to switch to PMode, as I had to deal with segments. I prefer zeroing everything, and then using flat segments in PMode or long mode. I think segmentation could be better, but it just needs some changes.Octocontrabass wrote:Gotta disagree with you there too. Setting segment registers to zero is much more convenient.
My original tool chain in 1988 was a DOS-based assembler & linker.Octocontrabass wrote:It's not a problem if you understand what it's doing and why. That's why we recommend being familiar with your toolchain.rdos wrote:and orgs are a bit problematic, especially if the linker/locator fills up with zeros.
I got a bit confused about this part.rdos wrote:I prefer to use the hidden sector count in the BPB to place the second stage boot loader directly after the MBR. When I partition a disc for my operating system, I always create a MBR with 16 hidden sectors and then the actual partitions will be after that.
I second that. It's easier to set the segment's base to 0. However I do the far jump rdos was talking about, because I've run into different BIOSes, some started the code at 0:7C00 and others at 07C0:0.nexos wrote:I agree with you, Octocontrabass.Octocontrabass wrote:Gotta disagree with you there too. Setting segment registers to zero is much more convenient.