Love4Boobies wrote:As for why MAGIC and FLAGS were on the stack in the loader, here's your answer. Apps are not what you are probably thinking they are. They're somewhat like normal procedure calls, where each app has main() called by the OS. The first "OS-stage" when booting the computer is the boot loader, which has to start the kernel. The loader you're using is Multiboot compliant (probably GRUB), and THAT's what pushes MAGIC and FLAGS to the stack so your kernel can pop them.
Whoa! Time out.
First of all, main() is not what's called by the OS. There's a small startup file that gets linked into every program, and this then calls main. The startup code is what takes care of things like setting up the runtime library, and initialising global objects for C++ code. When main returns, it's also responsible for calling the destructors of C++ objects, and finally calling the exit system call with main's exit code, which asks the OS to terminate the process. It's a small difference, but a crucial one, because a program which has main as its entry point will NOT work! main is a function like any other, so it expects to have a return address as well. Without startup code, returning from main would crash, or even return to a random memory location.
Secondly, the multiboot header, which includes the MAGIC and FLAGS, is not on the stack at all. The bootloader (GRUB) loads the kernel file from the disc (where exactly is specified in GRUB's configuration) and then looks in the first 8 kB of the file for the magic number. If it finds it, it loads the file according to the specifications following the magic number (or the ELF file header if it is an ELF binary) and then jumps to the specified entry point. From there, your kernel is in charge, but there is no stack at all until your kernel sets one up. To be more specific, until you set esp to a known value, you may not call any C-style functions and you may not activate interrupts (sti).
Since C functions depend on having a stack available, the entry point must be written in assembly. This entry 'stub' is much like the startup code of a regular program, and its job is to set things up so that you can jump into the main kernel function (kmain or something like it, you decide). The stub has to set up a stack at the very least. If you're using a higher-half kernel, then you must also set up the higher-half paging in the startup code before setting up the stack and calling the (k)main function, or all hell will break loose.
When GRUB starts your kernel, it sets EAX to the magic number 0x2BADB002, and EBX to the address of the multiboot information structure. When your kernel starts, you must first check that the EAX register equals 0x2BADB002. This is to make sure that your kernel was actually loaded by multiboot and not some other bootloader. The barebones tutorial just takes these values and pushes them onto the stack, so that they can be accessed as parameters from the kmain function, but does not check their values or do anything with them. Once you start to expand your kernel, you should check both of these values. Checking EAX within the startup code is what I do, and then I pass only EBX to kmain, but passing EAX to kmain as well works, as long as your startup code does not need any of the multiboot information. Your kernel must not use the multiboot information structure or even assume that it was loaded by multiboot at all until you've verified that EAX has the correct value.