Well, I guess this qualifies as an introduction

Programming, for all ages and all languages.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Well, I guess this qualifies as an introduction

Post by Combuster »

Mostly because it doesn't delve into the full details of the multiboot specification. When asked (which Bare Bones does by default), GRUB will give you the memory map as part of the information you get
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
blasthash
Member
Member
Posts: 31
Joined: Tue May 06, 2014 12:19 am

Re: Well, I guess this qualifies as an introduction

Post by blasthash »

Octocontrabass wrote:I think this is a good starting point. (Beware: although it does say that the machine state should be unchanged from what the BIOS left it in, you can't guarantee that the machine you're running on has a BIOS at all! It's better to assume that the BIOS is not available once GRUB is finished.)

And don't worry about feeling like an idiot - I've had plenty of those moments myself! :mrgreen:
When it says that the Multiboot address is present in EBX upon boot - that means that the address needs to be pulled immediately, before the main function has the chance to change it, right?
Octocontrabass
Member
Member
Posts: 5513
Joined: Mon Mar 25, 2013 7:01 pm

Re: Well, I guess this qualifies as an introduction

Post by Octocontrabass »

You should have a small assembly function, usually named "_start" or similar, that GRUB will jump to after loading your kernel. In there, you'll set up a stack, prepare the arguments, and call kmain. One of those arguments will probably need to be the value GRUB put in EBX.

You shouldn't name it "main"; compilers will get very mad at you.
blasthash
Member
Member
Posts: 31
Joined: Tue May 06, 2014 12:19 am

Re: Well, I guess this qualifies as an introduction

Post by blasthash »

Octocontrabass wrote:You should have a small assembly function, usually named "_start" or similar, that GRUB will jump to after loading your kernel. In there, you'll set up a stack, prepare the arguments, and call kmain. One of those arguments will probably need to be the value GRUB put in EBX.

You shouldn't name it "main"; compilers will get very mad at you.
I'll probably just create an inline-assembly function and run it as the very first thing in kernel_main(). Eventually, I'll figure out a way to work it into bootstrap, but I might put that until a day when I have a bit better grasp of assembly.
Octocontrabass
Member
Member
Posts: 5513
Joined: Mon Mar 25, 2013 7:01 pm

Re: Well, I guess this qualifies as an introduction

Post by Octocontrabass »

That won't work. The compiler can and probably will insert additional code before it. It has to be plain assembly.

You should probably try to avoid inline assembly, as well, since it's not portable and tends to hide bugs.
blasthash
Member
Member
Posts: 31
Joined: Tue May 06, 2014 12:19 am

Re: Well, I guess this qualifies as an introduction

Post by blasthash »

Octocontrabass wrote:That won't work. The compiler can and probably will insert additional code before it. It has to be plain assembly.

You should probably try to avoid inline assembly, as well, since it's not portable and tends to hide bugs.
Yeah, I knew myself that it would almost come out botched anyway. Just got a bad feeling when looking at the code.

The information on extracting the multiboot info from GRUB says that in the BB tuts, the bootstrap code there automatically pushes EBX to the stack for the MB struct. Well, I've been over that bootstrap code at least 10 times, and I can't find any line that has any semblance to what I know a call stack push should look like.

One of my "fatal flaws" as a work ethic is that I get to the point where I can't move on if things don't logically flow to me, and this GRUB multiboot isn't transparent to the point of me feeling uneasy writing code for it, even making the null assumption that I understood it more. Now, why is it that jumping down to real mode is a bad idea?
Octocontrabass
Member
Member
Posts: 5513
Joined: Mon Mar 25, 2013 7:01 pm

Re: Well, I guess this qualifies as an introduction

Post by Octocontrabass »

I'm not sure where you read that (I'm on my phone at the moment so I can't check), but I'm very certain that the function "void kernel_main()" doesn't take any parameters.

Of course, if your kernel_main takes parameters, then you should pass them according to the calling conventions.
blasthash
Member
Member
Posts: 31
Joined: Tue May 06, 2014 12:19 am

Re: Well, I guess this qualifies as an introduction

Post by blasthash »

Octocontrabass wrote:I'm not sure where you read that (I'm on my phone at the moment so I can't check), but I'm very certain that the function "void kernel_main()" doesn't take any parameters.

Of course, if your kernel_main takes parameters, then you should pass them according to the calling conventions.
On the Detecting Memory page, in the GRUB section:
To utilize the information that GRUB passes to you, first include the file multiboot.h in your kernel's main file. Then, make sure that when you load your _main function from your assembly loader, you push EBX onto the stack. The Bare bones tutorials have already done this for you.

The key for memory detection lies in the multiboot_info struct. To get access to it, you've already pushed it onto the stack...define your start function as such:

Code: Select all

_main (multiboot_info_t* mbd, unsigned int magic) {...}
[/b]
I'm not afraid to admit I'm 100% lost at what's going on at this point. The other things up to this point, the INT 0x15 method I can understand, but merging C and ASM is past my knowledge. I won't burden you further - I'll call it quits on this until I have the requisite knowledge sometime. This has stressed me out badly, and it hasn't been something I've been able to solve like other programming problems. Inlining I can understand because of how the operands work to return values, but mushing C and ASM together and passing arguments like that doesn't make sense to me, and again I'm not going to beat around that bush.
Octocontrabass
Member
Member
Posts: 5513
Joined: Mon Mar 25, 2013 7:01 pm

Re: Well, I guess this qualifies as an introduction

Post by Octocontrabass »

blasthash wrote:I'm not afraid to admit I'm 100% lost at what's going on at this point. The other things up to this point, the INT 0x15 method I can understand, but merging C and ASM is past my knowledge.
Time for more learning? It's not really that complicated, but you might get a better idea of what's going on if you write a small program and tell GCC to dump the generated assembly. (That would be "gcc -O0 -S", and possibly with "-masm=intel" if you don't like AT&T syntax. The "-O0" is to tell GCC to not optimize, so you can see how values are passed to functions.)
blasthash wrote:This has stressed me out badly, and it hasn't been something I've been able to solve like other programming problems.
Don't stress yourself out over it. Isn't this supposed to be for fun?
User avatar
bwat
Member
Member
Posts: 359
Joined: Fri Jul 03, 2009 6:21 am

Re: Well, I guess this qualifies as an introduction

Post by bwat »

blasthash wrote:One of my "fatal flaws" as a work ethic is that I get to the point where I can't move on if things don't logically flow to me,
That's not a fatal flaw! The Romans used to say something like "you can't give what you don't own". If you don't understand (own) it then you cannot build upon it or use it usefully (give). Now I'm older I realise that:

1) things take as long as they take, and
2) you have to build upon solid foundations.

Just make progress every day and before too long you'll be in a good position with proper hard won experience. You've got the rest of your life to master these things. Whatever you do, just don't give up!

Octocontrabass wrote:That would be "gcc -O0 -S"
I never bother learning calling conventions. I just look at the disassembly of functions similar to the assembly routine I want to write so it can be called by C code. I do just like you describe.
Every universe of discourse has its logical structure --- S. K. Langer.
blasthash
Member
Member
Posts: 31
Joined: Tue May 06, 2014 12:19 am

Re: Well, I guess this qualifies as an introduction

Post by blasthash »

Octocontrabass wrote:
blasthash wrote:I'm not afraid to admit I'm 100% lost at what's going on at this point. The other things up to this point, the INT 0x15 method I can understand, but merging C and ASM is past my knowledge.
Time for more learning? It's not really that complicated, but you might get a better idea of what's going on if you write a small program and tell GCC to dump the generated assembly. (That would be "gcc -O0 -S", and possibly with "-masm=intel" if you don't like AT&T syntax. The "-O0" is to tell GCC to not optimize, so you can see how values are passed to functions.)
blasthash wrote:This has stressed me out badly, and it hasn't been something I've been able to solve like other programming problems.
Don't stress yourself out over it. Isn't this supposed to be for fun?
Well, I took a day off from it. Didn't look at my kernel, tried not to do any reading on it, worked minimally on my other software projects, let my head clear a little bit. It's amazing what just taking a breather from a subject can do. This morning, as I was driving back into class, it popped in my head - let me know if I got this right:

Since the address of the boot table is stored into EBX after GRUB finishes, I'd configure an STDCALL/FASTCALL operation to forward it to kernel_main as an argument (as a pointer?). From then, all the reading of the table can be performed in C within the confines of kernel_main.

Code: Select all

int kernel_main (uint32_t *_bootloc)
{
    // Retrieval of the table via pointer can be done here, in C
}
Gah, that feels better. And yes, it is for fun - but I've always attacked all my projects as if they were a job - there are days I don't sleep when my iOS apps need writing - and I know there are multiple ways to accomplish things, but in something I'm not experienced with, during the boot of a computer as well, it's easy to get discouraged. I've always kept pummeling through my projects, never resting - this was the first time I consciously decided to shelve it for a day, and it worked.

I've actually written entire algorithms in ASM before (including things like AES-256 and other crypto algos), although usually they're in MIPS, which is more "spacious" (32 general purpose registers). I can look at assembly and have a rough idea of what goes on, but I can't "visualize" it and actively think in ASM the way I can in C languages (C/C++/Obj-C).

Let me know if that works. I'm anxious to get to writing it.
bwat wrote:
blasthash wrote:One of my "fatal flaws" as a work ethic is that I get to the point where I can't move on if things don't logically flow to me,
That's not a fatal flaw! The Romans used to say something like "you can't give what you don't own". If you don't understand (own) it then you cannot build upon it or use it usefully (give). Now I'm older I realise that:

1) things take as long as they take, and
2) you have to build upon solid foundations.

Just make progress every day and before too long you'll be in a good position with proper hard won experience. You've got the rest of your life to master these things. Whatever you do, just don't give up!

Octocontrabass wrote:That would be "gcc -O0 -S"
I never bother learning calling conventions. I just look at the disassembly of functions similar to the assembly routine I want to write so it can be called by C code. I do just like you describe.
Very true. I'd much rather work to understand it because then I can work it to my own purposes, as opposed to just having the code handed to me. Again, it's amazing what giving the mind a little rest and relaxation can do.
Octocontrabass
Member
Member
Posts: 5513
Joined: Mon Mar 25, 2013 7:01 pm

Re: Well, I guess this qualifies as an introduction

Post by Octocontrabass »

blasthash wrote:Since the address of the boot table is stored into EBX after GRUB finishes, I'd configure an STDCALL/FASTCALL operation to forward it to kernel_main as an argument (as a pointer?). From then, all the reading of the table can be performed in C within the confines of kernel_main.
That sounds right, although I'd probably try CDECL first since that's (roughly) what GCC uses by default.

Technically you should pass a pointer to a struct instead of a pointer to uint32_t, but I wouldn't worry about it unless GCC starts to complain.
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Well, I guess this qualifies as an introduction

Post by sortie »

cdecl? stdcall? fastcall? What the ****? That's Windows calling conventions. If you are using a i686-elf cross-compiler as documented in Bare Bones, you are using the System V ABI.

All you need to do is preserve the value originally in the ebx register somehow (and eax, since that's a magic value) and pass it as a parameter to the kernel main function in accordance with the ABI in use.
User avatar
Bender
Member
Member
Posts: 449
Joined: Wed Aug 21, 2013 3:53 am
Libera.chat IRC: bender|
Location: Asia, Singapore

Re: Well, I guess this qualifies as an introduction

Post by Bender »

Code: Select all

int kernel_main (uint32_t *_bootloc)
{
    // Retrieval of the table via pointer can be done here, in C
}
Why not use structures? The multiboot information is given to the kernel inside a structure. Check this out: (Specifically the multiboot_info) http://www.gnu.org/software/grub/manual ... 002eh.html
This should be of interest too: http://www.gnu.org/software/grub/manual ... rnel_002ec
"In a time of universal deceit - telling the truth is a revolutionary act." -- George Orwell
(R3X Runtime VM)(CHIP8 Interpreter OS)
blasthash
Member
Member
Posts: 31
Joined: Tue May 06, 2014 12:19 am

Re: Well, I guess this qualifies as an introduction

Post by blasthash »

First things first, I'll go down the list. My apologies everyone, the Fedora partition decided to brick my MacBook Pro; now I have to get everything off and wipe it back to default.
Octocontrabass wrote:
blasthash wrote:Since the address of the boot table is stored into EBX after GRUB finishes, I'd configure an STDCALL/FASTCALL operation to forward it to kernel_main as an argument (as a pointer?). From then, all the reading of the table can be performed in C within the confines of kernel_main.
That sounds right, although I'd probably try CDECL first since that's (roughly) what GCC uses by default.

Technically you should pass a pointer to a struct instead of a pointer to uint32_t, but I wouldn't worry about it unless GCC starts to complain.
How would I orient the pointer to a struct? Just have something like struct boot_table *header in the arguments? (I'm a bit heavy-handed still with pointers; even though I've been working for the longest time in Objective-C which is ideally a superset of C, pointers have become somewhat vestigial)

The reason I originally used uint32_t was because of the fact that EBX is a 32-bit capable register. If I went the struct pointer route, how would I interpret
sortie wrote:cdecl? stdcall? fastcall? What the ****? That's Windows calling conventions. If you are using a i686-elf cross-compiler as documented in Bare Bones, you are using the System V ABI.

All you need to do is preserve the value originally in the ebx register somehow (and eax, since that's a magic value) and pass it as a parameter to the kernel main function in accordance with the ABI in use.
First of all, judging from the first part of your reply, calm down. If you read with a bit more context, the specifying of specific conventions was more out of getting a grip on the specific practice, not a plan to use one of those conventions per se.

As per the Calling Conventions page (under GCC/x86) - is the process of passing in the parameter as simple as:

Code: Select all

push ebx
call kernel_main
?
Bender wrote:

Code: Select all

int kernel_main (uint32_t *_bootloc)
{
    // Retrieval of the table via pointer can be done here, in C
}
Why not use structures? The multiboot information is given to the kernel inside a structure. Check this out: (Specifically the multiboot_info) http://www.gnu.org/software/grub/manual ... 002eh.html
This should be of interest too: http://www.gnu.org/software/grub/manual ... rnel_002ec
This is due to a number of reasons, none of which will most likely hold up under any scrutiny.

1. At this point, I want to get the hang of reading into and withdrawing from memory manually, because I know there's certainly more of it. Using a pre-made struct means I don't have to do the manual handling of the address and retrieval, which albeit hard, is what I want to do. I'd rather learn the hard way on this, although I'm not heart-set against it.

2. My main concern is with my laptop down and my lack of a development machine currently (I'm using my account on my dad's machine right now), I don't want to have to install GNU dependencies and libraries (on a Windows 7 machine at that) on a computer I don't exert day-to-day control over. Doing the process manually, I can write the code even on paper without needing dependent libraries in my system.

As I've tried to show so far, I'm welcoming of any reason to reconsider.
Post Reply