Asm to C and Back

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.
newwen
Posts: 16
Joined: Sun Feb 03, 2008 3:04 am

Asm to C and Back

Post by newwen »

OK, I am going give it a shot to ask this question here.

I have a boot loader written in asm using NASM, (I don't use GRUB), I don't use ELF, I am working on a Windows System for Windows, and I am assembling my loader using a flat-binary format. My problem is I am not able to use ORG or EXTERN when using the flat-binary format, so my question is:

Keeping with the same flat-binary format, how can I call an external function in my C Kernel from my ASM boot loader and vice versa?

Thanks
User avatar
AJ
Member
Member
Posts: 2646
Joined: Sun Oct 22, 2006 7:01 am
Location: Devon, UK
Contact:

Post by AJ »

Hi,

Why can't you use ORG? This works for me in NASM.

To call a C function, from ASM, you need to know what linkage your compiler uses. If it is GCC, the 32 bit default is to push all arguments right-to-left, then do a call. The caller removes pushed arguments. If you don't have a properly set up cross compiler and don't use a command line switch, you may find that gcc adds a leading underscore to the c function names. In this way, 'main' becomes '_main'. So, to call main:

Code: Select all

push eax  ;argv
push ebx  ;argc
call [main] ;or call [_main]
pop ebx
pop eax  ;caution about this - gcc returns the first integer parameter in eax!
To call ASM from C, it's fairly easy - you just have to handle the pushed registers nicely - generally, you use ebp to mark the function's 'stack frame'.

In 64 bit mode, all this changes and parameters are passed in registers be default. See the System V ABI for details.

Cheers,
Adam
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:

Post by Combuster »

The only real solution is not to use the assembler to create a flat binary, but have the linker do that.
"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 ]
DeletedAccount
Member
Member
Posts: 566
Joined: Tue Jun 20, 2006 9:17 am

This should be helpful

Post by DeletedAccount »

newwen
Posts: 16
Joined: Sun Feb 03, 2008 3:04 am

Post by newwen »

@AJ AND SandeepMathew: Thanks for your replies they were helpful.

@Combuster: Then how would you set up my compilation script:

Code: Select all

@echo off
set PATH=c:\djgpp\bin;%PATH%
set DJGPP=c:\djgpp\djgpp.env
chdir c:\djgpp\toy os\src

call del.bat

nasm-2.01rc1\nasm -w-orphan-labels -f bin x86boot.asm -o x86boot.bin

c:\djgpp\bin\gcc  -ffreestanding -c -o main.o main.c
c:\djgpp\bin\gcc -c video.c -o video.o
c:\djgpp\bin\gcc -c ports.c -o ports.o

c:\djgpp\bin\ld -e _main -Ttext 0x1000 -o kernel.o main.o video.o ports.o

c:\djgpp\bin\ld -i -e _main -Ttext 0x1000 -o kernel.o main.o video.o ports.o
c:\djgpp\bin\objcopy -R .note -R .comment -S -O binary kernel.o kernel.bin

c:\djgpp\bin\makeboot a.img x86boot.bin kernel.bin

pause
thanks
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Post by 01000101 »

why do you need to 'call' the C code from your bootloader, why don't you just jump to either a second-stage bootloader and then use the 'extern' feature, or just jump straight to your C code?

Why don't you load your binary off of the floppy and then jump to it wherever you placed it?
newwen
Posts: 16
Joined: Sun Feb 03, 2008 3:04 am

Post by newwen »

@01000101 (E): Nice! I like that, secondary boot loader. I could treat it as an object and do all my stuff from there. I wouldn't mind writing my stuff in asm like the GDT/IDT stuff, but my reason for needing to call some code in my loader is so that I can flush the GDT/IDT when I use it with IO. I do everything else in C, however.

@combuster: does PE == coff in NASM?

@mods: why haven't you hacked the forum to show the posts to these threads as we create/edit posts? I kept forgetting the names of the people I was trying to respond to, plus I would forget what they even said and it sucks to have to keep going back and forth between pages. I'll write you a solution if necessary just to make my life easier while I am here. Hope you get it fixed.
newwen
Posts: 16
Joined: Sun Feb 03, 2008 3:04 am

Post by newwen »

Update: OK, somehow I managed to make it assemble without changing anything.. just yesterday I wasn't able to use extern or global and today I can?

Well, here is what I am trying to do:

Code: Select all

jmp 08h:01000h          ; Jump to section 08h (code), offset 01000h
		
[GLOBAL test]
test:
jmp$
That is a section of my boot loader. I placed in the jmp to show that I have already jmp'd to my kernel, then in my kernel:

Code: Select all

extern void test();

void main()
{
        printf("blah");
	test();
}
I do that, but when I assemble I get this:
main.o:main.c:(.text+0x6f): undefined reference to `test'
1 sectors, 512 bytes read from file x86boot.bin...
2 sectors, 1008 bytes read from file kernel.bin...
Press any key to continue . . .
So, it assembled and linked, but when I run it I see the text "blah" and get a system crash; which tells me that my assembler code is not being called, or else it would hang thus being the equivalent of C's for(;;);

So, what am I doing wrong?
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post by JamesM »

why haven't you hacked the forum to show the posts to these threads as we create/edit posts?
You can see them when you create but not when you edit. Scroll down.
newwen
Posts: 16
Joined: Sun Feb 03, 2008 3:04 am

Post by newwen »

Oh, you are right, they are there. We should still see them when we make edits though. Also, any idea about what is going wrong with my code?
User avatar
bloodhound23
Member
Member
Posts: 115
Joined: Wed Jan 23, 2008 7:13 pm
Contact:

Post by bloodhound23 »

use fasm if you want a flat binary.
I thought I wasn't thinking, I thought wrong.
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:

Post by Combuster »

The problem is that you must make two different programs be able to talk with one another. That means you'll need some way to have one program know where to reach the other program. Given the level in which you are, we can pretty much rule out dynamic linking and system calls.

The only two real options I can see is not to call a bootloader from the kernel. Probably the best thing.
The other option is to not make two programs, but rather one, which essentially means that you put the kernel and bootloader in a single binary so that at least LD can figure where everything's located.

Given the fact that you do not seem to know in detail how your tools work, I really suggest you review the architecture of your system. Once you exit the bootloader you should not be coming back.

@bloodhound23: you do not need to use fasm to get a flat binary. nasm/yasm can do those natively as well. You can even assemble with gas and use ld to create a flat binary.
"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 ]
newwen
Posts: 16
Joined: Sun Feb 03, 2008 3:04 am

Post by newwen »

@combuster: OK, that is what I thought, if I jmp outside the loader I would not be able to reference the code inside it anymore, it makes sense to me that it works that way, which is why I included that line in my example for the hopes that someone would notice it and know right away what I am doing wrong, and you did.

No, I don't care what my level is, tell me what is right to do, not what is possible for me right now! I want to know what should be done. I know since I code for Windows, that makes me an outcast in this community. Many of the guides and tips do not apply to me, mainly the ones that use ELF and GRUB, which is nearly all!! However, it is the code I care about. You are not born knowing how to do this kind of thing, so it is helpful to learn from others which is why I ask so many questions. It isn't like I will be new forever, I learn fast enough, but only when I am being taught the right thing and in the right way. One line replies do nothing for me, I am a hands-on learner.

I hope that I can co-exist here peacefully, I promise to not burden you too much with my obsessive questioning.. lol

Anyway, I guess I will just ask someone else. thanks

P.s. How do I delete my account or can you do it for me?
User avatar
01000101
Member
Member
Posts: 1599
Joined: Fri Jun 22, 2007 12:47 pm
Contact:

Post by 01000101 »

jmp 08h:01000h ; Jump to section 08h (code), offset 01000h

shouldn't this be:

asm

Code: Select all

global _test
_test:
    hlt
    ret
C

Code: Select all

extern void test(); 

void main() 
{ 
        printf("blah"); 
        test(); 
} 
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:

Post by Combuster »

newwen wrote:@combuster: OK, that is what I thought, if I jmp outside the loader I would not be able to reference the code inside it anymore, it makes sense to me that it works that way, which is why I included that line in my example for the hopes that someone would notice it and know right away what I am doing wrong, and you did.
Well, if you expected it, why didn't you tell us? You probably didn't mean it like that, but we rather help people who are straight and have looked for an answer rather than one playing games asking questions trying to figure who knows the right answer. That feels like wasting my time.
No, I don't care what my level is, tell me what is right to do, not what is possible for me right now! I want to know what should be done. I know since I code for Windows, that makes me an outcast in this community. Many of the guides and tips do not apply to me, mainly the ones that use ELF and GRUB, which is nearly all!! However, it is the code I care about. You are not born knowing how to do this kind of thing, so it is helpful to learn from others which is why I ask so many questions. It isn't like I will be new forever, I learn fast enough, but only when I am being taught the right thing and in the right way. One line replies do nothing for me, I am a hands-on learner.
I think we just hit the spot where your skill "level" is indeed important. Programming for windows is hardly the same thing as programming an OS. I regularly program for windows too (I even won competitions with windows apps), but I don't think I'm an outcast here, merely strange (*cough* freebasic *cough*). An operating system is *not* windows, an OS does *not* run under windows. Instead it runs on bare metal. You have no task manager that can kill your program when it goes awry. Knowing what GRUB can do for you is the start of your quest. Knowing what ELF and PE are allows you to make your own choice. That both do not apply to you is nonsense. You should know them to make an educated decision about using them or not.
Anyway, I guess I will just ask someone else. thanks
Seriously, people never learn to work on their own if we keep feeding them the answers. Rather, they should try and understand how things work and then put that knowledge to good use. Going somewhere else to be fed with the answers doesn't help you in the long run.
P.s. How do I delete my account or can you do it for me?
You can't, I can't.
"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 ]
Post Reply