6

I found that usually programmers fixup registers (and sometimes segments) on their very first lines of bootloaders and they advice usually to have this habit. For instance:

inc cx
dec bx
inc bp
dec di
xor ax, ax

What I know is that: BIOS clears all registers during the boot procedure!

Is it a good habit to initialize registers and segments in a bootloader? Why? What are the default registers, segments and pointers value (Maybe chipset dependent)?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 3
    The Intel documentation does specify what value each register contains when the CPU is powered up. But you are asking about the state after the BIOS hands off to the bootloader, so who knows... – Nayuki Apr 12 '17 at 02:45
  • Thank you @Nayuki. You are right. – محمد جعفر نعمة Apr 12 '17 at 02:53
  • 8
    By the time you get to the bootloader executing there is about only one thing you can assume (with the exception of some 1980s era not so compatible computers). That is the drive lnumber that was booted by the BIOS is in the _DL_ register beyond that you should make no assumptions about the state of the flags, state of the segment registers and the state of any general purpose register. – Michael Petch Apr 12 '17 at 02:55
  • 1
    Thank you @MichaelPetch. Always helpful. – محمد جعفر نعمة Apr 12 '17 at 02:58
  • @MichaelPetch, IMO that should be an answer. – Johan Apr 13 '17 at 08:37
  • @MichaelPetch What about the stack? Can I use it? I mean, if the BIOS uses it (for interrupts at the very least), I suppose it can be used? – SasQ Sep 18 '20 at 21:15
  • @MichaelPetch Oh, one more thing: is there some way to discover the particular values of all those registers set up by the BIOS? If stack could be used, I could simply push them on the stack to avoid messing them up, then I could read them from the stact one by one and display them as hex on the screen. But if stack cannot be used, is there some other way to figure them out without messing them up? – SasQ Sep 18 '20 at 21:17
  • @SasQ The stack could be anywhere in the first megabyte of RAM and you may not actually know how much space is available before it overwrites a data area you may be using. It is generally a better idea to set the stack somewhere where you know it is safe from what you are doing. But nothing stops you from reading the `SS` segment and the `SP` register to determine where the current stack pointer is. – Michael Petch Sep 18 '20 at 21:20

1 Answers1

9

Since you mention settings of segment registers and your code appears to be 16-bit code I will assume you are discussing legacy IBM-PC bootloaders (PC-BIOS) and not (EFI/UEFI). In legacy bootloaders for the majority of equipment that has been manufactured there is very little you can assume.

By the time the PC-BIOS loads the boot sector from an available boot device and transfer control to it the state of all the registers but one have a usable value. With the exception of some non-standard (and not 100% compatible BIOSes) from the 80s and 90s the register DL will contain the boot drive number the BIOS booted from. This value is also the one used to call Int 13h disk service routines.

SS:SP likely points to somewhere in RAM but where that is differs from BIOS to BIOS. One should setup their own stack pointer (SS and SP) especially if you intend to load data into memory. You could unintentionally overwrite the stack with data unless you specifically set it yourself.

Some argue that CS:IP are always set to 0x0000:0x7c00 (CS=0x0000, IP=0x7c00) when control is transferred to your bootloader (usually through a FAR JMP). Unfortunately this isn't guaranteed. Some bootloaders are known to use 0x07c0:0x0000 which also points to physical address 0x07c00 (0x07c0<<4+0x0000). This is because different segment:offset addressing can represent the same physical address (like 0x07c00). I wrote a Stackoverflow question/answer that captures a situation where assuming CS is always 0x0000 can lead to some interesting bugs depending on the environment.

The direction flag (DF in FLAGS register) used for the string instructions (like CMPS and MOVS) should not be assumed to be a particular direction. Most code uses forward movement (DF=0) but there is no guarantee that is the direction the BIOS set it to before jumping to the bootloader. Because of that one should explicitly clear it with CLD for forward movement or set it with STD for backward movement.

Besides the aforementioned DL register you should not assume any of the general purpose registers are initialized at all. Often I see bootloaders that assume they are zero. This is almost never the case.

Many of these things are discussed in my Stackoverflow General Bootloader Tips.

Community
  • 1
  • 1
Michael Petch
  • 46,082
  • 8
  • 107
  • 198