Writing bootloader with includes... [Solved. Mostly...]

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
TheGameMaker90
Member
Member
Posts: 83
Joined: Thu Jan 07, 2021 2:01 pm

Re: Writing bootloader with includes...

Post by TheGameMaker90 »

neon:
I am aware of this. The goal is to call macros in c header from my GAS assembly bootloader.

foliagecanine:
Yes. Exactly. But generating a .bin (or linking them) is an entirely different thing. Say I generate the .o file. Great. Now how do I test it? See my problem? I already generated the object files.
This is how I did it (follow these steps to see what I mean):
- Create a file called boot.S
- Fill it in with this code:

Code: Select all

.code16
.text
.globl _start
_start:
    . = _start + 510
    .word 0xAA55
- Type the following into the terminal: as boot.S -o boot.o
- Then this: ld -Ttext 0x7C00 --oformat=binary boot.o -o boot.bin
- You should see boot.bin and boot.o

Phase 2:
- Add .include "boot.h" under .text
- Create boot.h and put in the following:

Code: Select all

#ifnedef __ASSEMBLER__
#define BOOT_MAGIC        0xAA55
#else
// ...
#endif
- Next run the same commands in the terminal.
Output: ld: boot.o: in function `_start':
(.text+0x1fe): undefined reference to `BOOT_MAGIC'

Calling functions into assembly is a goal, but I like to take it in steps. That'll likely be the next topic :wink: .

As far as the -m32 is concerned, no you're right. That should be ommitted, but it just proves my point that I've tried everything. That's left over from when I was trying to do this before my attempts at using my i686-elf.
And I know. I'm just trying to get a functional 16 bit real mode bootloader up and running, then switch to protected mode and run some tests.This isn't planned to be a two minute endeavor.

I tried what you said with i686-elf-ld:
And once again I got the same result :( .

Edit:
I realized something: I was doing .include. That only works if I compile it using GAS. Realizing that I followed your advice and lo and behold it worked. Thank you.

For future readers:
If you're running into the same issue, it might be worth looking into the way you're doing things. A simple symbol (chanhing a '.' to a '#') could be your problem. And if you're using your own cross compiler or following with the "Building your own cross compiler" tutorial, don't use i686-elf-gcc then use the standard LD. They're apparently incompatible.

I was even able to test with a C file (to avoid conflict with boot.o). It doesn't do anything yet (just a simple test function), but we'll see how it goes.
Last edited by TheGameMaker90 on Fri May 21, 2021 9:28 pm, edited 1 time in total.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Writing bootloader with includes...

Post by neon »

Hi,
I am aware of this. The goal is to call macros in c header from my GAS assembly bootloader.
If that is the intent behind this thread: then why is their discussion on boot loaders and linking which has nothing to do with the goal? Additionally, the resolution to meet this goal has already been answered in the second or third post of this thread: so why is this continuing?

Additionally, what benefit does it provide to use a c header file for an assembly boot loader? If the goal is to write a c boot loader then you are doing it wrong. I assert this as my boot loader is in c and there is a lot of details not addressed in this thread. The only other possible reason to share a c header file with the kernel is to define a standard boot protocol interface such as the multiboot standard.
Last edited by neon on Fri May 21, 2021 9:36 pm, edited 1 time in total.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
TheGameMaker90
Member
Member
Posts: 83
Joined: Thu Jan 07, 2021 2:01 pm

Re: Writing bootloader with includes...

Post by TheGameMaker90 »

Well, because it's a starting point. And because it simply states "Writing a bootloader with includes." Is the end result not using them? And yes, read the post just above your head. It has everything to do with linking them. And for your last question, I redirect you to what I just said. It wasn't answered until now.
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: Writing bootloader with includes...

Post by kzinti »

Mmm no. The preprocessor and linking have nothing to do with each others. I think you might be very confused.
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: Writing bootloader with includes...

Post by bzt »

TheGameMaker90 wrote:I just want to replace GRUB.
Then try BOOTBOOT. It was specifically written for people who don't like GRUB (like myself). Plus it does the boot sector "linking" and bootable disk creation for you that you're so misunderstanding.
TheGameMaker90 wrote:The goal is to call macros in c header from my GAS assembly bootloader.
Ah, that's not possible. The Assembly includes the header, and not the other way around, therefore the header has no knowledge what's in the bootloader. Plus it is not possible to write macros neither in C nor in Assembly, that's a job for the pre-compiler. What you can do is having a header with pre-compiler macros, that both your C and your Assembly sources use, as I've already explained.

Cheers,
bzt
Octocontrabass
Member
Member
Posts: 5567
Joined: Mon Mar 25, 2013 7:01 pm

Re: Writing bootloader with includes...

Post by Octocontrabass »

TheGameMaker90 wrote:- Type the following into the terminal: as boot.S -o boot.o
The C compiler will run the C preprocessor on assembly files with particular extensions. The assembler will not. If you want to use the C preprocessor on your assembly files, you must use i686-elf-gcc here.
TheGameMaker90 wrote:- Add .include "boot.h" under .text
The C preprocessor will only run on files included using C preprocessor directives. If you want to use the C preprocessor on your header files, you must use #include here.
TheGameMaker90 wrote:

Code: Select all

#ifnedef __ASSEMBLER__
The __ASSEMBLER__ macro is defined only when the C compiler runs the C preprocessor on an assembly files. You're telling the C preprocessor that you don't want to define BOOT_MAGIC in your assembly files. Undefined tokens are treated as labels by default.

Once you fix all of these issues, i686-elf-ld should no longer complain about undefined labels.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Writing bootloader with includes...

Post by neon »

Hi,
Well, because it's a starting point. And because it simply states "Writing a bootloader with includes." Is the end result not using them? And yes, read the post just above your head. It has everything to do with linking them. And for your last question, I redirect you to what I just said. It wasn't answered until now.
I appended my above post as I have created a c boot loader that have done precisely what you are requesting. Not to mention I implemented an assembler and compiler - I must have just forgot about having to use a linker to process those complex include directives rather then a simple file stack. But hey, by all means continue and good luck.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
TheGameMaker90
Member
Member
Posts: 83
Joined: Thu Jan 07, 2021 2:01 pm

Re: Writing bootloader with includes...

Post by TheGameMaker90 »

kzinti:
Mmm yes. I am aware of that. As I already pointed out this has been solved by foliagecanine when he provided me with the i686-elf-ld which I forgot even existed. If you look back on the posts I didn't bring up the preprocessor. bzt did. I just wanted to generate a .bin from my .o files and would get that error every time I did. Knowing that it was a linkage error I took it to here. I even said at one point "I already know about that and the C macro, that is not my concern, although it might be useful to somebody who does not know about it."

bzt then wrote:
"Well, yes and no. Yes, you can share the same header file with both, and they both can share the same definitions. But no, you can't put Assembly and C things in that header. You have to limit yourself to a syntax that's common to both, which is not much, mostly pre-compiler stuff (parts which aren't common must be #ifdef guarded)."

Up to that point I was only talking about linking into a bin. That's what I meant when I said "Hi there, I've been trying to replace GRUB (because of its limitations and for proprietary reasons) and I was wondering how I could theoretically include say a c header from GAS assembly." in the first post. I just wanted to get rid of that error which said that it couldn't find the macro I defined in boot.h.

Now do you see?

bzt:
Thank you, that would be an option if I hadn't stated " I've been trying to replace GRUB (because of its limitations and for proprietary reasons)." If I wanted a prebuilt bootloader I could just stick with GRUB. It get's the job done, but I want access to the 16-bit code GRUB omits (or hides very far away :P ).
And yes, that's my point. I'm not trying to call assembly code in my header. Please quote me on where I stated that. And yes, just imagine aheader file with a list of macro's in the preprocessor for my bootloader. Just look at GRUB's source. I basically want to do that myself.

Octocontrabass:
Yes you are right. I changed it when I realized that. I did that before, I just forgot about it until now (which is how it usually works).
I'm going to have to refer you to the post where I said it was solved :P.
And yeah, sorry. I have a habit of putting that 'n' in there. In my code it's actually:

Code: Select all

#ifdef __ASSEMBLER__
#define BOOT_MAGIC    0xAA55
#else
// ...
#endif
neon:
Just saw your post as I was writing this (switching between pages for my quotes refreshed the page).
The way you described it was difficult to understand. And that's great! But I do sense the sarcasm. Complex includes? This thread is taking wayyy too long to close. All of this could have been avoided if one of you just posted a reply like foliagecanine did. That's all I was asking for. Not a lecture on preprocessors. His reply:
Secondly, remember you are NOT linking your kernel to your bootloader. They are two separate entities.
If you are using LD the way the website does, you should be doing "i686-elf-ld -Ttext 0x7c00 --oformat=binary boot.o –o boot.bin"
MAKE SURE you are using i686-elf-ld, rather than standard ld. They are built for different architectures.
was all I needed.
Octocontrabass
Member
Member
Posts: 5567
Joined: Mon Mar 25, 2013 7:01 pm

Re: Writing bootloader with includes...

Post by Octocontrabass »

TheGameMaker90 wrote:I'm going to have to refer you to the post where I said it was solved :P.
No fair, you solved it before I finished writing my reply! :roll:
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Writing bootloader with includes... [solved]

Post by neon »

Hi,

Indeed that was meant to be sarcastic as we tried to explain that #include's don't have anything to do with the linker: because they don't. No matter, nice to see you got what you wanted solved. Any case, good luck.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
TheGameMaker90
Member
Member
Posts: 83
Joined: Thu Jan 07, 2021 2:01 pm

Re: Writing bootloader with includes...

Post by TheGameMaker90 »

Octocontrabass wrote:
TheGameMaker90 wrote:I'm going to have to refer you to the post where I said it was solved :P.
No fair, you solved it before I finished writing my reply! :roll:
Too slow! Just kidding, but maybe there is something you could assist me with.
Now I'm on the part where I want to perform another test. I want to call an assembly function in c and have a function called boot_main in bootloader.c.
My assembly function will just initalize the terminal:

Code: Select all

.globl init_terminal
init_terminal:
    mov $03, %ax
    int $0x10

    mov $01, %ah
    mov $0, %ch
    mov $7, %cl
    int $0x10

Code: Select all

So I call in to bootloasder.c with
extern void init_terminal(void);

void boot_main(void)
{
    init_terminal
}
then call it in the assembly file under _start

Code: Select all

_start:
    call init_terminal
And nothing changes. It's supposed to set it to tty mode and render a block cursor. Is it not possible to do it that way?

neon:
I figured and no hard feelings. It just wasn't letting me link it with the includes. Now do you understand? And thank you. I will indeed continue working on this.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Writing bootloader with includes... [solved]

Post by neon »

Hi,

"linker error - ld: i386 architecture of input file is incompatible with i386:x86-64 output" would have been for sure a better subject.

The confusion I believe started from the original post which asked 4 completely unrelated questions:

"I was wondering how I could theoretically include say a c header from GAS assembly."
"The problem is, I don't know how to compile the .S file with the C header"
"but how do I turn it into a binary that QEMU can run"
"when I use LD it says: ld: i386 architecture of input file `boot.o' is incompatible with i386:x86-64 output."

Lets take a look at your stated goal:

"The goal is to call macros in c header from my GAS assembly bootloader."

But the stated solution solves an unrelated issue that you posted in the original post:

"when I use LD it says: ld: i386 architecture of input file `boot.o' is incompatible with i386:x86-64 output."

You may believe that this is related to headers but its not at all. If the error triggers only when using headers thats fine -- but this is a linker error and should have been emphasized in the original post. The main compiler only sees the preprocessed .c file (no headers at all) which is used to generate the object file in the end. You can even have the compiler output the preprocessed file if you want to see -- all of this occurs way before any linker is invoked.

My suggestion is to be more careful with how you write the original post and put an emphasize on the main item you want solved.
Last edited by neon on Fri May 21, 2021 10:47 pm, edited 1 time in total.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
TheGameMaker90
Member
Member
Posts: 83
Joined: Thu Jan 07, 2021 2:01 pm

Re: Writing bootloader with includes... [solved]

Post by TheGameMaker90 »

neon wrote:Hi,

"linker error - ld: i386 architecture of input file is incompatible with i386:x86-64 output" would have been for sure a better subject.

The confusion I believe started from the original post which asked 4 completely unrelated questions:

"I was wondering how I could theoretically include say a c header from GAS assembly."
"The problem is, I don't know how to compile the .S file with the C header"
"but how do I turn it into a binary that QEMU can run"
"when I use LD it says: ld: i386 architecture of input file `boot.o' is incompatible with i386:x86-64 output."

Lets take a look at your stated goal:

"The goal is to call macros in c header from my GAS assembly bootloader."

But the stated solution solves an unrelated issue that you posted in the original post:

"when I use LD it says: ld: i386 architecture of input file `boot.o' is incompatible with i386:x86-64 output."

You may believe that this is related to headers but its not at all. If the error triggers only when using headers thats fine -- but this is a linker error and should have been emphasized in the original post.

My suggestion is to be more careful with how you write the original post and put an emphasize on the main item you want solved.
Okay fair point on the naming. And no. They are not unrelated. They are the steps to do what I did. The first two are rewordings of each other.
GAS assebly uses the suffix .S (for assembly files that use C macro's for instance. That is what I read somewhere once). The thirt is the output once it is linked.And the fourth is the result I got. When I created the post I had no idea what the issue was so I listed my steps and results. And yes, it only had this problem when I started trying to include C headers.
Octocontrabass
Member
Member
Posts: 5567
Joined: Mon Mar 25, 2013 7:01 pm

Re: Writing bootloader with includes...

Post by Octocontrabass »

TheGameMaker90 wrote:Is it not possible to do it that way?
It's possible, but it definitely won't work if you forget RET at the end of your function, and you need to tell the compiler to emit 16-bit code, and you need to obey the compiler's ABI, and you need to load enough sectors from the disk because compiled C will quickly outgrow the one sector the BIOS loads for you.

You might want to consider splitting the bootloader into two or more stages, where the first stage is written entirely in assembly to fit within the single sector provided by the BIOS.

You might want to consider switching the CPU to 32-bit protected mode for your C code, and using a wrapper around BIOS interrupts that switches the CPU to real mode before calling the BIOS and back to 32-bit protected mode after the call returns.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Writing bootloader with includes... [solved]

Post by neon »

Hi,
The first two are rewordings of each other.
GAS assebly uses the suffix .S (for assembly files that use C macro's for instance. That is what I read somewhere once). The thirt is the output once it is linked.And the fourth is the result I got.
Additional suggestion in the future: If you are describing a process that you have executed that yielded an error (in this case, a linker error -- which is the whole point of this thread), write it just like what you did above. In practice, there should be the steps that you use to produce the error, expected result and actual result.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
Post Reply