views:

175

answers:

4

Hello,

I have messed around a few times by making a small assembly boot loader on a floppy disk and was wondering if it's possible to make a boot loader in c++ and if so where might I begin? For all I know im not sure it would even use int main().

Thanks for any help.

A: 

Bootloaders don't have "int main()"s, unless you write assembly code to call it. If you are writing a stage 1 bootloader, then it is seriously discouraged.

Otherwise, the osdev.org has great documentation on the topic.
While it is probably possible to make a bootloader in C++, remember not to link your code to any dynamic libraries, and remember that just because it is C++, that doesn't mean you can/should use the STL, etc.

luiscubal
If it is C++, you can use the STL. That is end-of-story. If you can't use the STL, it's not C++.
DeadMG
If it has a tail it's a dog, if it has not it's not a dog end of story
kriss
Thanks the site has a lot of good info.
happyCoding25
@DeadMG You can't possibly be serious. STL is an API, not the language. It's a bootloader. Period. That means no "new"/"delete" keywords unless you explicitly define them, no File I/O, unless you explicitly define your own file functions. In others words, unless you statically link a standard library specifically designed for these purposes, or write your own STL, you won't be able to use almost anything from the STL. And, either way, it might be a bad idea to use it anyway.
luiscubal
@luiscubal: If you compile in C++, your compiler is obliged to provide you with a new/delete implementation. I'm not going to argue whether or not you should. But, those are facts of C++ life, that those implementations and those headers are mandatory of a C++ compiler. If you can compile C++ for the "bootloader" environment, then it's the compiler's job to solve the aforementioned problems and provide for you an STL to use. The technical difficulties of implementing the STL in a bootloader environment are not the problem of the user of said compiler- they just make it unlikely such exists.
DeadMG
@DeadMG new/delete are the C++ equivalent for malloc/calloc/free. If there is NO malloc/calloc/free, how do you expect C++ to provide you with those? There is NO new/delete in bootloader C++ unless you write your own new/delete operator implementations.
luiscubal
@DeadMG Also, g++ is available and works. Never tried it with bootloaders, but I can assure you that it works with kernels, which have the same limitations. Do some investigation next time before spreading wrong information. The link I provided in my answer is a pretty good start. See http://wiki.osdev.org/C%2B%2B and go to the section "the operators new/delete", which I basically just quoted in this answer/comments. Last but not least, there can't be a standard library in this case because code as low-level as this is compiled with -nostdlib. Not compiling it with -nostdlib is suicide.
luiscubal
@DeadMG And, while we're at it, notice that there the page recommends disabling exceptions and RTTI. And yet, it *IS* C++.
luiscubal
@luiscubal: If there is no malloc/calloc/free provided by a host OS, then the C++ compiler must provide it's own. If you can, why can't the compiler? The difficulty of implementation is not C++'s concern. As for the G++ environment you have described, that is not C++. It's C with classes. It is not a C++ compiler for that platform. Go read the C++ standard. Breaking news: It makes the rules on what is C++ and what isn't. Higher-level languages are easier to use because they have more built-in. If you have to implement your own exceptions, why not just use assembler direct?
DeadMG
@DeadMG No. You don't need to use every single C++ feature to have a C++ application. For instance, I've wrote programs in C that didn't use fscanf. Does that mean they aren't C? No. Just because you don't use a feature of the language(or standard API), that doesn't mean it's no longer the language. A program written in a subset of C++ is still a C++ program. The C++ won't provide its own malloc/calloc/free, nor new/delete. The PROGRAMMER who is using C++ to write the bootloader implements it. The host OS doesn't provide it because THERE IS NO HOST OS.
luiscubal
@luiscubal: Doesn't use != not available. If you didn't use fscanf, that doesn't mean it's not C, but if it's not available, that does. And, it's not incumbent on the OS to provide it. It's incumbent on the compiler. Most compilers can just fall back on the OS, but if there is no OS, that's the compiler's problem to write that code for you to make it work.
DeadMG
@DeadMG: He didn't ask if there were C++ compilers for bootloaders(which, by your definition, there are not), he asked if he could write bootloaders in C++, which he definitively can.
luiscubal
+1  A: 

Yes it is possible. You have elements of answer and usefull links in this question

You also can have a look here, there is a C++ bootloader example.

The main thing to understand is that you need to create a flat binary instead of the usual fancy executable file formats (PE on windows, or ELF on Unixes), because these file format need an OS to load them, and in a boot loader you don't have an OS yet.

Using library is not a problem if you link statically (no dynamic link because again of the above executable problem). But obviously all OS API related entry points are not available...

kriss
+1  A: 

It's been a while since I played with writing bootloaders, so I'm going off memory.

For an x86 bootloader, you need to have a C++ compiler that can emit x86 assembly, or, at the very least, you need to write your own preamble in 16-bit assembly that will put the CPU into 32-bit protected (or 64-bit long) mode, before you can call your C++ functions.

Once you've done that, though, you should be able to make use of most, if not all, of C++'s language features, so long as you stay away from things that require an underlying libc. But statically link everything without the CRT and you're golden.

greyfade
+4  A: 

If you're writing a boot loader, you're essentially starting from nothing: a small chunk of code is loaded into memory, and executed. You can write the majority of your boot loader in C++, but you will need to bootstrap your own C++ runtime environment first.

Assembly is really the only option for the first stage, as you need to set up a sensible environment for running anything higher-level. Doing enough to run C code is fairly straightforward -- you need:

  • code and data loaded in the right place;
  • there may be an additional part of the data area which must be zero-initialised;
  • you need to point the stack pointer at a suitable area of memory for the stack.

Then you can jump into the code at an appropriate point (e.g. main()) and expect that the basic language features will work. (It's possible that any features of the standard library that may have been implemented or linked in might require additional initialisation at this stage.)

Getting a suitable environment going for C++ requires more effort, as it needs more initialisation here, and also has core language features which require runtime support (again, this is before considering library features). These include:

  • running static constructors;
  • memory allocation to support new and delete;
  • support for run-time type information (RTTI);
  • support for exceptions;
  • probably some other things I've forgotten to mention.

None of these are required until the C environment is up and running, so the code that handles these can be written in C rather than assembler (or even in a subset of C++ that does not make use of the above features).

(The same principles apply in embedded systems, and it's not uncommon for such systems to make use of C++, but only in a limited way -- e.g. no exceptions and/or RTTI because the runtime support isn't implemented.)

Matthew Slattery