Page 1 of 1

Mixing asm code and c code.

Posted: Thu Apr 22, 2010 11:18 am
by sav1or
Hello.
My problem is how to pass control to my c code from bootloader? I used http://www.osdever.net/tutorials/view/mixing-assembly-c tutorial , but it is not working :(
Are there any other ways to do it?

Re: Mixing asm code and c code.

Posted: Thu Apr 22, 2010 12:23 pm
by Combuster
There's no other way to get access to C code than doing this in assembly:

Code: Select all

call my_function_name
All other methods are hacks, which is one of the reasons the tutorial is bogus and can easily refuse to work (for one, main = 0x1000 is not guaranteed, attempts to return from main will cause crashes).

Re: Mixing asm code and c code.

Posted: Thu Apr 22, 2010 12:54 pm
by Owen

Code: Select all

void out(unsigned short _port, unsigned char _data)
{
   __asm__ ("out %%al, %%dx" : : "a" (_data), "d" (_port));
}
* Owen cries. People need to learn of and use GCC's "r" specifier... #-o

Re: Mixing asm code and c code.

Posted: Thu Apr 22, 2010 1:01 pm
by gravaera
And to know how to program as well...

Or at least rtfm before posting...

Re: Mixing asm code and c code.

Posted: Thu Apr 22, 2010 1:07 pm
by NickJohnson
Well, there are other possible ways to call a C function, but none simpler than "call <function>". If you are part of some odd programming cult that dislikes "call", or are part of an obfuscated code contest:

Code: Select all

mov eax, .done
push eax
jmp main
.done:
or even more obfuscated:

Code: Select all

xor ebx, ebx
mov eax, $
cmp ebx, 1
je .done
push eax
mov ebx, 1
jmp main
.done:
:twisted:

Re: Mixing asm code and c code.

Posted: Thu Apr 22, 2010 2:22 pm
by tharkun
Owen wrote:* Owen cries. People need to learn of and use GCC's "r" specifier... #-o
Yes but consider these two pieces of code:

Code: Select all

inline void outb (uint16_t port, uin8_t value)
{
    asm volatile ("outb %0, %1" :: "a" (value), "dN" (port));
}

Code: Select all

inline void outb (uint16_t port, uint8_t value)
{
    asm volatile ("outb %0, %1" :: "r" (value), "r" (port));
}
In the first example the outb command, will always work for any input. However, in the second example you don't know that value and port will end up in the right registers, e.g al and dx.

Re: Mixing asm code and c code.

Posted: Thu Apr 22, 2010 2:35 pm
by NickJohnson
Why use inline assembly at all? It's compiler and architecture specific no matter how you slice it: external assembly is only architecture specific.

Re: Mixing asm code and c code.

Posted: Thu Apr 22, 2010 2:45 pm
by Owen
pinged wrote:
Owen wrote:* Owen cries. People need to learn of and use GCC's "r" specifier... #-o
Yes but consider these two pieces of code:

Code: Select all

inline void outb (uint16_t port, uin8_t value)
{
    asm volatile ("outb %0, %1" :: "a" (value), "dN" (port));
}

Code: Select all

inline void outb (uint16_t port, uint8_t value)
{
    asm volatile ("outb %0, %1" :: "r" (value), "r" (port));
}
In the first example the outb command, will always work for any input. However, in the second example you don't know that value and port will end up in the right registers, e.g al and dx.

Crap. I forgot the ioio instructions were still hobbled with regards to the supported registers.

Re: Mixing asm code and c code.

Posted: Thu Apr 22, 2010 2:51 pm
by gravaera
You can use architecture specific includes and have the asm inline, with the right include file selected based on the architecture being compiled for, NickJohnson. Most ASM snippets are small bits of code that are oft repeated, and lots of times in tight loops where the cost of an extra memory reference (the push on the call instruction) is a desirable thing to optimize out.

I think that's really the main reason to use inline ASM as opposed to calling and returning from a single snippet.

--All the best,
gravaera

Re: Mixing asm code and c code.

Posted: Thu Apr 22, 2010 7:27 pm
by NickJohnson
Premature optimization is the root of all evil...

At least in my OS, there are no instances of assembly snippets for anything other than special instructions (loading/saving control regs, invlpg, sti/cli, in/out, etc.), which are either not in tight loops or expensive to the point that a single function call overhead is meaningless. The only instance where this is not true is with semaphore operations in userspace, which are used in enough places to deter the compiler from placing them inline anyway. To me, not having to adjust anything for different compilers (my kernel compiles under gcc, tcc, and clang with no preprocessor switches) is more valuable than a couple microseconds here and there.

I can't tell why exactly this thread went OT about inline asm though...

Re: Mixing asm code and c code.

Posted: Fri Apr 23, 2010 5:49 am
by sav1or
tnks for all. problem solved =D>

Re: Mixing asm code and c code.

Posted: Fri Apr 23, 2010 9:49 am
by Owen
NickJohnson wrote:Premature optimization is the root of all evil...

At least in my OS, there are no instances of assembly snippets for anything other than special instructions (loading/saving control regs, invlpg, sti/cli, in/out, etc.), which are either not in tight loops or expensive to the point that a single function call overhead is meaningless. The only instance where this is not true is with semaphore operations in userspace, which are used in enough places to deter the compiler from placing them inline anyway. To me, not having to adjust anything for different compilers (my kernel compiles under gcc, tcc, and clang with no preprocessor switches) is more valuable than a couple microseconds here and there.

I can't tell why exactly this thread went OT about inline asm though...
You are aware GCC, TCC and CLang all use the same inline assembly syntax? #-o

Re: Mixing asm code and c code.

Posted: Fri Apr 23, 2010 2:25 pm
by NickJohnson
I wouldn't know: I don't use inline assembly! My point is that I avoid extensions that would break compatibility between any compilers; I consider inline assembly to be an extension. Perhaps a better way to say it is that my kernel compiles with "-std=c99 -pedantic".