What is inline assembly good for ?
Re: What is inline assembly good for ?
Good. Tried to merge some things and clean the article up a bit.
Can someone check the new version, especially for English correctness since I am not a native English writer?
Can someone check the new version, especially for English correctness since I am not a native English writer?
Re: What is inline assembly good for ?
Hi,
That's just gcc,These are the compilers that I have predominantly worked with
Turbo C / Borland C / Digital Mars use asm{}
Note that the position of the brace is important esp in the freely available Turbo C++ 1.01 Compiler ,the brace should come right after the asm keyword.Possibly a bug
Visual C++ uses __asm
--Thomas
That's just gcc,These are the compilers that I have predominantly worked with
Turbo C / Borland C / Digital Mars use asm{}
Code: Select all
asm{
mov ax , 0x4c00
int 0x21
}
Visual C++ uses __asm
Code: Select all
__asm
{
mov al, 2
mov dx, 0xD009
out dx, al
}
Last edited by Thomas on Wed May 05, 2010 2:18 am, edited 1 time in total.
- xenos
- Member
- Posts: 1118
- Joined: Thu Aug 11, 2005 11:00 pm
- Libera.chat IRC: xenos1984
- Location: Tartu, Estonia
- Contact:
Re: What is inline assembly good for ?
Code: Select all
int current_task;
asm( "ltr %[output]"
: [output] "=r" (current_task)
);
Code: Select all
int current_task;
asm( "str %[output]"
: [output] "=r" (current_task)
);
Code: Select all
"movl %0, %%es" : "=r" (x)
As for the original topic, I like the way GCC handles inline assembly. GCC's operand constraint syntax offers the possibility to let the compiler choose which register(s) to use from a given set of registers, or choose memory or constant operands instead. The compiler can thus optimize the assembler code as well, which would not be possible if it was located in a separate file with fixed registers.
Of course there are some drawbacks with inline assembly. The first one is that inline assembly syntax is highly compiler dependent, so before using it, one must choose a compiler. This is not a major drawback for me, since I use GCC most of the time, as it fits my needs: It is fast, optimizing, and targets plenty different architectures. And of course it is open source and so on.
Another drawback that has been mentioned in this thread is that inline assembly is not portable between different target architectures. Of course this is true. This is the reason why I use inline assembly only for architecture specific code. (A typical example is x86 paging code: Of course, an instruction like "movl %0, %%cr3" works only for x86 or x86_64, but this paging code will be used only for these, anyway.) There are some situations where a similar operation can be performed on different architectures, but with different instructions. An example for this are spinlocks. Most architectures support an atomic test-and-set instruction, but these may look completely different. In this case, I use something similar to this:
Code: Select all
// AtomicLock.h
#include <config.h>
class AtomicLock
{
private:
volatile int key;
public:
void Enter(void);
void Exit(void);
};
#include INC_ARCH(AtomicLock.h)
Code: Select all
#define INC_ARCH(x) <arch/x86/x>
Code: Select all
// arch/x86/AtomicLock.h
inline void AtomicLock::Enter(void)
{
asm volatile ("1: \n"
"pause \n"
"lock btsl $0, %[key] \n"
"jc 1b" : : [key] "m" (key));
}
inline void AtomicLock::Exit(void)
{
asm volatile ("movl $0, %[key]" : : [key] "m" (key));
}
Code: Select all
// arch/m68k/AtomicLock.h
inline void AtomicLock::Enter(void)
{
asm volatile ("1: \n"
"bsetb #0, %[key] \n"
"beqs 1b" : : [key] "m" (key));
}
inline void AtomicLock::Exit(void)
{
asm volatile ("movel #0, %[key]" : : [key] "m" (key));
}
Re: What is inline assembly good for ?
About other compilers, guess it should be interesting to write some separate articles for MS and Borland inline assembly and mention it in this article (ex : in the new overview section, by something like "this is about GCC, if you're using MSVC go here"). Since I don't know these much, I let you do it.
GCC should remain in the "Inline Assembly" article, IMO, as it's the most used compiler, and the most documented compiler in the wiki. This way, one gets quick access to the most probable answer, while still having access to the less common options.
1/Because it changes original GAS register syntax, where they could have used a new syntax like <variable name> instead.
2/Because it is error-prone : if you add an output operand in a code using input operands, you must rewrite the whole part of your code which uses them.
I don't fully understand the logic behind the new [] syntax either : it's better, but why not just use the output operand names right away ? It sounds more intuitive and less error-prone, while the benefit of doing otherwise is very small... (EDIT : Looking at the new wiki entries, I wonder if it's not possible already)
EDIT : Well, it looks like Creature joined the rewrite effort, and started improving the wiki too. That's great ! I opened a page in order to discuss the wiki issue in more details here : http://forum.osdev.org/viewtopic.php?f=8&p=175981
GCC should remain in the "Inline Assembly" article, IMO, as it's the most used compiler, and the most documented compiler in the wiki. This way, one gets quick access to the most probable answer, while still having access to the less common options.
Gee... I didn't check the examples from the original article enough, even though I already found some horrors in places Now it's fixed. Thanks for your participation !XenOS wrote:should probably beCode: Select all
int current_task; asm( "ltr %[output]" : [output] "=r" (current_task) );
You store the task register, you don't load it And another one:Code: Select all
int current_task; asm( "str %[output]" : [output] "=r" (current_task) );
I guess there is no output operand here, but an input operand instead.Code: Select all
"movl %0, %%es" : "=r" (x)
Yup, I'm starting to sort of like it too as I begin to understand how it works, but I still think that the %x thing is a horrible mistake.As for the original topic, I like the way GCC handles inline assembly. GCC's operand constraint syntax offers the possibility to let the compiler choose which register(s) to use from a given set of registers, or choose memory or constant operands instead. The compiler can thus optimize the assembler code as well, which would not be possible if it was located in a separate file with fixed registers.
1/Because it changes original GAS register syntax, where they could have used a new syntax like <variable name> instead.
2/Because it is error-prone : if you add an output operand in a code using input operands, you must rewrite the whole part of your code which uses them.
I don't fully understand the logic behind the new [] syntax either : it's better, but why not just use the output operand names right away ? It sounds more intuitive and less error-prone, while the benefit of doing otherwise is very small... (EDIT : Looking at the new wiki entries, I wonder if it's not possible already)
Well, this is more of a general problem with assembly, and not specific to inline assembly, isn't it ?Another drawback that has been mentioned in this thread is that inline assembly is not portable between different target architectures. Of course this is true. This is the reason why I use inline assembly only for architecture specific code. (A typical example is x86 paging code: Of course, an instruction like "movl %0, %%cr3" works only for x86 or x86_64, but this paging code will be used only for these, anyway.) There are some situations where a similar operation can be performed on different architectures, but with different instructions. (...)
EDIT : Well, it looks like Creature joined the rewrite effort, and started improving the wiki too. That's great ! I opened a page in order to discuss the wiki issue in more details here : http://forum.osdev.org/viewtopic.php?f=8&p=175981
- xenos
- Member
- Posts: 1118
- Joined: Thu Aug 11, 2005 11:00 pm
- Libera.chat IRC: xenos1984
- Location: Tartu, Estonia
- Contact:
Re: What is inline assembly good for ?
I agree. At the beginning I was quite confused because of the additional %'s and used to forget them, with strange results.Neolander wrote:Yup, I'm starting to sort of like it too as I begin to understand how it works, but I still think that the %x thing is a horrible mistake.
1/Because it changes original GAS register syntax, where they could have used a new syntax like <variable name> instead.
2/Because it is error-prone : if you add an output operand in a code using input operands, you must rewrite the whole part of your code which uses them.
In principle, yes. But the advantage of GCC's syntax is that you can have different operands sharing the same register. For example, you can have something like:I don't fully understand the logic behind the new [] syntax either : it's better, but why not just use the output operand names right away ? It sounds more intuitive and less error-prone, while the benefit of doing otherwise is very small...
Code: Select all
asm ("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "0" (function));
But I also like MSVC syntax, where you can to something like this:
Code: Select all
struct
{
int first;
int second;
} data;
...
__asm
{
mov eax, &data
mov ecx, [eax].first
mov edx, [eax].second
}
Yes, that's true. The problem with inline assembly is that it introduces this architecture dependence into the C source code, which otherwise could in principle be compiled targetting any architecture (even though it doesn't make sense, e.g. compiling x86 paging code for a M68K target). But especially in OS development, there are some things that simply must be architecture specific, and I don't see any disadvantage in putting them directly into some (architecture specific) C file via inline assembly. (Apart from the compiler dependence, of course.)Well, this is more of a general problem with assembly, and not specific to inline assembly, isn't it ?
Re: What is inline assembly good for ?
I have used inline asm in some cases but I always favor just putting it in a .s or .asm file and call it from c using an extern command.
Note I don't know how much more performance benifit it gives but using the .s file way saves me a headache in most cases.
Can somebody tell me how much performance benifit you are getting from it?
Basically a function call only pushes the return address and the parameters on the stack and then does your code pop's a few things and returns so if you had N parameters their would be N+1 pushes and one mov for the return value into EAX or so... then N+1 pops and a jmp to the return address
So another words 2N+2 operations plus a 2 jmp command (one for jumping to the function another for jumping back)
So final formula 2N+4 and maybe some extra pushs and move's to manipulate the parameters ,...etc
I guess it can be come a big savings if you have alot of varibles or alot of function calls to this.
Note I don't know how much more performance benifit it gives but using the .s file way saves me a headache in most cases.
Can somebody tell me how much performance benifit you are getting from it?
Basically a function call only pushes the return address and the parameters on the stack and then does your code pop's a few things and returns so if you had N parameters their would be N+1 pushes and one mov for the return value into EAX or so... then N+1 pops and a jmp to the return address
So another words 2N+2 operations plus a 2 jmp command (one for jumping to the function another for jumping back)
So final formula 2N+4 and maybe some extra pushs and move's to manipulate the parameters ,...etc
I guess it can be come a big savings if you have alot of varibles or alot of function calls to this.
Re: What is inline assembly good for ?
If you want to play it really ugly, you can put the inline assembly into a seperate file and #include that file where you need it. Add a couple of #ifdef's for compiler and platform, and you got portable "inline" assembly.
Sorry, nasty mood today.
Sorry, nasty mood today.
Every good solution is obvious once you've found it.