Can I use function macros inside gcc inline assembly block? - gcc

#define MOV_MACRO(R0,R1)\
{\
"mov R0, R1 \n\t"\
}
__asm__ volatile(\
MOV_MACRO(r4,r5)
:"r4","r5"\
);\
Is it possible to use a function like this in an asm block ?
If not, please suggest ways to use it.

Yes, it's possible, but if you need such functionality you probably shouldn't be using inline asm but a separate asm module.
#define MOV_MACRO(R0,R1) "mov " #R0 ", " #R1 "\n\t"
void foo()
{
__asm__ volatile(
MOV_MACRO(r4,r5)
::
:"r4","r5"
);
}

Related

How to set a bit in Control Register (cr0) with inline assembly?

I'm trying to set bit 30 of cr0 register with inline assembly. I'm using the following assembly in my kernel module,
__asm__ (
"mov %%cr0, %%rax\n\t"
"or 0x40000000, %%eax\n\t"
"mov %%rax, %%cr0\n\t"
::
:"%rax"
);
My module compiles but upon inserting the module my terminal freezes. From a new terminal when I try to remove the module, it shows the following,
rmmod: ERROR: Module xxx is in use
and dmesg shows the following in red color,
RIP [<ffffffffc09c604c>] hello_start+0x4c/0x1000 [ModuleName]
how to set control register 0 (cr0) bits in x86-64 using gcc assembly on linux and Trying to disable paging through cr0 register also talk about the same problem. I try to follow their solution but I just can't make it work. Any help, where am I making mistake in my inline assembly?
Update post:
I have fixed the code according #prl suggestions, following is my full source code,
u64 get_cr0(void){
u64 cr0;
__asm__ (
"mov %%cr0, %%rax\n\t"
"mov %%eax, %0\n\t"
: "=m" (cr0)
: /* no input */
: "%rax"
);
return cr0;
}
static int __init hello_start(void){
printk(KERN_INFO "Loading hello module...\n");
printk(KERN_INFO "Hello world\n");
printk(KERN_INFO "cr0 = 0x%8.8X\n", get_cr0());
__asm__ (
"mov %%cr0, %%rax\n\t"
"or $0x40000000, %%eax\n\t"
"mov %%rax, %%cr0\n\t"
::
:"%rax"
);
printk(KERN_INFO "cr0 after change = 0x%8.8X\n", get_cr0());
return 0;
}
static void __exit hello_end(void){
printk(KERN_INFO "Goodbye Mr.\n");
__asm__ (
"mov %%cr0, %%rax\n\t"
"and $~(0x40000000), %%eax\n\t"
"mov %%rax, %%cr0\n\t"
::
:"%rax"
);
}
Indeed, my system is running super slow after loading the module. But after changing the bit I still did not see any difference in cr0 register value. Following is the output in dmesg
[ +0.000400] Loading hello module...
[ +0.000001] Hello world
[ +0.000002] cr0 = 0x80050033
[ +0.000312] cr0 after change = 0x80050033
[ +6.085675] perf interrupt took too long (2522 > 2500), lowering kernel.perf_event_max_sample_rate to 50000
Why can't I see the change in bit 30 of the cr0 register?
Therefore, Upon removing the module, I tried to clear bit 30 hoping my system will start to respond normally. But seems like that did not work. My system is still running slow. Any thoughts, how to bring back the system to its normal functional state after modifying the cr0?

how to let Inline assembly pass -O1 optimization

I have following dispatch code for my user level thread library.
The code can pass GCC and runs correctly without optimization, but if I choose -O1 optimization (also higher levels), when run the code, program generates segmentation fault.
Basically the function does save context and jump to next context.
void __attribute__ ((noinline)) __lwt_dispatch(lwt_context *curr, lwt_context *next)
{
__asm__ __volatile
(
"mov 0xc(%ebp),%eax\n\t"
"mov 0x4(%eax),%ecx\n\t"
"mov (%eax),%edx\n\t"
"mov 0x8(%ebp),%eax\n\t"
"add $0x4,%eax\n\t"
"mov 0x8(%ebp),%ebx\n\t"
"push %ebp\n\t"
"push %ebx\n\t"
"mov %esp,(%eax)\n\t"
"movl $return,(%ebx)\n\t"
"mov %ecx,%esp\n\t"
"jmp *%edx\n\t"
"return: pop %ebx\n\t"
"pop %ebp\n\t"
);
}
Thanks for help, I figured out some ways to solve it.
Normally compile this function as a separate .o file then use O3 to optimize it with other files.
using inline assembly is much easier and simpler than this function. Like below:
int foo = 10, bar = 15;
asm volatile("addl %%ebx,%%eax"
:"=a"(foo)
:"a"(foo), "b"(bar)
);
printf("foo+bar=%d\n", foo);
Another post has helped me figuring out labeling problem, see here: Labels in GCC inline assembly

error: invalid 'asm': operand number missing after %-letter when using inline assembly with GCC

I'm tring to convert a simple assembly code of MS to use with gcc, the MS assembly I try to convert is right below. I have two int variables, number and _return:
mov eax, number
neg eax
return, eax
and, I have tried this:
asm("movl %eax, %0" :: "g" ( number));
asm("neg %eax");
asm("movl %0, %%eax" : "=g" ( return ));
But, the compiler gives me this error:
main.c:17:9: error: invalid 'asm': operand number missing after %-letter
Where is the error, and, how I can fix this error?
Thanks
You can't do it like that because you're overwriting registers without telling the compiler about it. Also, the % is a special character, similar to printf.
It's also better to put all the instructions in one asm or else the compiler might do something unexpected in between.
Try this instead:
asm("movl %%eax, %1\n\t"
"neg %%eax\n\t"
"movl %0, %%eax" : "=g" ( _return ) : "g" ( number) : "eax");
There's probably a better way, though:
asm("neg %0": "=a" ( _return ) : "a" ( number));
I don't know why you can't just do (in C):
_return = -number;
Try something like:
#include <stdio.h>
#include <stdlib.h>
int main(int ac,char**av)
{
int n=ac>1?atoi(av[1]):42;
asm ("movl %0, %%eax \n\t"
"neg %%eax \n\t"
"movl %%eax, %0 \n\t" : "+r" (n)::"eax");
printf("%d\n",n);
}
The issues are:
order of operands is instr src,dst
%% instead of %
no isolated lines of assembler -- the input/output/clobber list is associated to all of the assembler block
'+r' to have a parameter that works as both input & output
I doubt even MS allows using keyword "return" that way
And to make it even more efficient:
asm("neg %0" : "+r" (n) ::); // works as well

GCC inline assembly error: Error: junk `(%esp)' after expression

GCC inline assembly error: Error: junk `(%esp)' after expression
I'm studying gcc inline assembly. My environment is Win 7 32bit, mingw-gcc 4.6.1.
I have got a problem about the 'm' constraint. Here is my c function code:
static int asm_test(int a, int b)
{
int c = 0;
__asm__ __volatile__(".intel_syntax\n"
"mov eax, %1\n" //error
"mov edx, %2\n" //error
"add eax, edx\n"
"mov %0, eax\n" //error
".att_syntax"
:"=m"(c)\
:"m"(a),"m"(b)\
:"eax","edx"
);
return c;
}
For at&t code, it is like this:
static int asm_test(int a, int b)
{
int c = 0;
__asm__ __volatile__(
"movl %1, $eax\n" //error
"movl %2, $edx\n" //error
"addl $edx, $eax\n"
"movl $eax, %0\n" //error
:"=m"(c)\
:"m"(a),"m"(b)\
:"eax","edx"
);
return c;
}
For each of the three lines which operate input/output operands, gcc generate an error when compiling, read like this:
C:\Users\farta\AppData\Local\Temp\cc99HxYj.s:22: Error: junk `(%esp)' after expression
If i use 'r' for input/output constraint, the code will work. But I cannot understand why it works and what the error stands for. Can anyone tell me? As far as I know 'm' is just telling gcc not to allocate registers but directly access them in memory if inline asm code try to access input/output operands. Is this correct?
Thanks a lot.
The problem here is the GCC generates AT&T syntax construct for %0, %1 and %2. If you look at the generated assembly, it looks like:
.intel_syntax
mov eax, 8(%ebp)
mov edx, 12(%ebp)
add eax, edx
mov -4(%ebp), eax
which is not a valid Intel syntax.
Generally, you don't need to include in the inline assembly explicit load/store operation - just specify register constraint and the compiler will generate loads/stores by itself. This has the advantage that even if your variables (parameters, locals) do not reside in memory at all, but are in registers your code will still be correct - unlike in the case if you explicitly put memory load/stores there.
For your example, try the following code, look at the assembly (gcc -S) and notice how the compiler will perform moves from argument area (e.g. stack on x86) all by itself.
int asm_test(int a, int b)
{
__asm__ __volatile__ (
".intel_syntax\n"
"add %0, %1 \n"
".att_syntax \n"
:"+r"(a)
:"r"(b));
return a;
}

arm inline assembly code and compiler optimization's options

I'm trying to du some inline assembly code.
My function is
void pixemcpy(unsigned char *im_src, unsigned char *im_dest, int npix)
{
int i;
for(i=0;i<npix;i++) *im_dest++=*im_src++;
}
My assembly inline function is
void inline_pixelcpy(unsigned char *im_src, unsigned char *im_dest, int npix){
__asm__ volatile(
"0: \n"
"ldrb r3, [%[src]], #1 \n"
"strb r3, [%[dst]], #1 \n"
"subs %[iter], %[iter], #1\n"
"bgt 0b\n"
:
: [src] "r" (im_src), [dst] "r" (im_dest), [iter] "r" (npix)
: "cc", "r3"
);
}
Both function are in the same c file!
When I compile my c file that's work's ! Both function do the same thing there is no problem.
If I use -O2 or -O3 gcc option, I have a segmentation fault when returning (not calling) my assembly function !
This problem do not occured if my 2 function are into separate files !
Is there a problem into my inline code ! How can I tell to gcc to not try to optimise my inline code !
thank's
Etienne

Resources