This question already has answers here:
What does a double-percent sign (%%) do in gcc inline assembly?
(3 answers)
What is r() and double percent %% in GCC inline assembly language?
(4 answers)
Inline assembly : register referencing conventions
(1 answer)
Closed 2 years ago.
I want to get the process id of my test C program but I don't understand what I'm doing wrong with my inline assembly code.
When I write
pid_t pid;
asm volatile ( // Basic asm statement (never use)
"movl $20, %eax"
"int $0x80"
);
// editor's note: this is unsafe, never do it this way.
// You don't tell the compiler EAX is overwritten, among other problems.
asm volatile ( // Extended asm statement
"movl %%eax,%0"
: "=r"(pid)
);
the variable pid gets exactly the value I expect. However I can't get this working together in an extended assembly call as written here:
https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html
If I try something like this
asm volatile (
"movl $20, %eax"
"int $0x80"
"movl %%eax,%0"
: "=r"(pid)
);
GCC (run by Visual Studio Code) gives me the error message:
error: invalid 'asm': operand number missing after %-letter
So why can this work in two separate calls but the moment I call it as extended asm it doesn't anymore?
Related
This question already has answers here:
What is the colon in the c language between two strings?
(1 answer)
What is the difference between 'asm', '__asm' and '__asm__'?
(4 answers)
Using inline assembly with serialization instructions
(1 answer)
CPUID implementations in C++
(3 answers)
How to use CPUID instruction to get x86 CPU features correctly? [duplicate]
(1 answer)
Closed 10 hours ago.
I'm working with some low-level C code and I don't quite understand what's going on here:
/* Description of the current CPU. */
struct cpuid { unsigned eax, ebx, ecx, edx; };
/* Return information about the CPU. See <http://wiki.osdev.org/CPUID>. */
static struct cpuid
cpuid (unsigned int leaf, unsigned int subleaf)
{
struct cpuid result;
asm ("cpuid"
: "=a" (result.eax), "=b" (result.ebx),
"=c" (result.ecx), "=d" (result.edx)
: "a" (leaf), "c" (subleaf));
return result;
}
I've tried looking for information on the asm() function, including that wiki page, but I'm still struggling in deciphering the code. I understand that the : syntax is an old-school, deprecated way to initialize structs, but I don't really see how it's working here.
edit:
my question is specifically about what this snippet of code is doing, not the syntax or any of that. just this section and what's going on.
This question already has answers here:
The difference between asm, asm volatile and clobbering memory
(3 answers)
What does __asm__ __volatile__ do in C?
(3 answers)
Closed 5 years ago.
int __attribute__ ((noinline)) mySystemCall (uint32 Exception, uint32 Parameter)
{
#ifdef PROCESSORX
__asm__ volatile ("sc")
#else
__asm__ __volatile__ ("mov R0, %0; mov R1, %1; svc 0x0 " : : "r" (Exception), "r" (Parameter));
}
How does the compiler translate the instruction (asm volatile ("sc"))?
Why are some arguments passed as strings and some are not (ex:
__asm__ __volatile__("rdtsc": "=a" (a), "=d" (d) ))
Inline assembly isn't specified by the C standard. I assume this is code for gcc and compatible, then you should have a look at the manual.
As for your specific questions:
How does the compiler translate the instruction (asm volatile ("sc"))?
The volatile in this context instructs the compiler that the assembler snippet must be included, even if the compiler can't see a reason it's actually needed for the behavior of the program. Whatever comes in the first string parameter is literal assembly code of the target platform.
Why are some arguments passed as strings and some are not
It's just part of the syntax, refer to the manual I listed above. Inline assembly can "bind" input and output parameters to C variables and also tell the compiler which registers are "clobbered" by the assembly snippet (among other things).
Inline assemblers have to bridge the gap between C and assembly so in addition to ones assembly code, one needs to give details of how they interact. The first item in the GCC assembly template is the actual assembly, the other items include assigning input variables, output variables and clobbers (registers/memory) that the assembly may clobber so C need to steer clear of. The full details may be found: here.
This question already has an answer here:
How to embed LLVM assembly or intrinsics in C program with Clang?
(1 answer)
Closed 9 years ago.
I was looking enviously at the ability to put inline assembler in code compiled by GCC, and I'm wondering if you could do something similar with Clang? For example is there some way I could complete the definition of a function with LLVM assembler:
int add_two_ints(int a, int b) {
/*
* some bitcode stuff goes here to add
* the ints and return the result
*/
}
Any references, or code to complete the example above would be great.
clang supports inline assembly, including GCC's extension where you declare input, output, and clobbered registers:
int add_two_ints(int a, int b) {
int result;
asm( "addl %1, %2;"
"movl %2, %0;"
: "=r"(result)
: "r"(a), "r"(b)
:);
return result;
}
Clang also has experimental support for Microsoft's __asm { } syntax and intel style assembly.
It does not have any support for including LLVM-IR in C or C++ source. Such a feature would largely be just a novelty as inline assembly is typically for accessing special instructions and LLVM-IR doesn't enable that.
I'm writing inline assembly statements using a GNU-based toolchain, and there are three instructions within the inline assembly to update a single bit of a system register. The steps will be:
move(read) a system register to a general register
'AND' it with the variable value from C code
move(write) back to the system register just read
in the instruction set I'm using, the inline assembly syntax is like this:
unsigned int OV_TMP = 0xffefffff;
asm volatile ( "mfsr %0, $PSW\n\t"
"and %0, %0, %1\n\t"
"mtsr %0, $PSW"
: : "r"(OV_TMP) : );
%1 is the register which I want to forward the value of OV_TMP into.
%0 is the problem for me, and my problem is :
How to write the inline assembly code once there is a register used internally and is not assigned from nor copy to the C variables in the C code?
The thing to consider here is that, from the compiler's perspective, the register is assigned-to by the inline assembly, even if you don't use it again later. That is, you're generating the equivalent of:
register unsigned int OV_TMP = 0xffefffff, scratch;
scratch = magic() & OV_TMP;
more_magic(scratch);
/* and then don't re-use scratch for anything from here on */
The magic and/or more_magic steps cannot be moved or combined away because of the volatile, so the compiler cannot simply delete the written-but-unused register.
The mfsr and mtsr look like powerpc instructions to me, and I would probably do the and step in C code (see footnote); but the following should generally work:
unsigned int OV_TMP = 0xffefffff, scratch;
asm volatile("mfsr %0, $PSW\n\t"
"and %0, %0, %1\n\t"
"mtsr %0, $PSW"
: "=&r"(scratch) : "r"(OV_TMP));
Here the "=&r" constraint says that the output operand (%0) is written before the input operand (%1) is read.
Footnote: As far as I know (which is not very far, I've only ever done a tiny bit of ppc assembly) there's no need to keep the mfsr and mtsr instructions a specific distance apart, unlike certain lock-step sequences on other processors. If so, I would write something more like this:
static inline unsigned int read_psw() {
unsigned int result;
asm volatile("mfsr %0, $PSW" : "=r"(result));
return result;
}
static inline void write_psw(unsigned int value) {
asm volatile("mtsr %0, $PSW" :: "r"(value));
}
#define PSW_FE0 0x00100000 /* this looks like it's FE0 anyway */
...
write_psw(read_psw() & ~PSW_FE0); /* some appropriate comment here */
I am trying to use a thread local variable in inline assembly, but when I see the diassembled code, It appears that the compiler doesn't generate the right code. For the following inline code, where saved_sp is globally declared as __thread long saved_sp,
__asm__ __volatile__ (
"movq %rsp, saved_sp\n\t");
The disassembly looks like the following.
mov %rsp,0x612008
Which is clearly not the right thing, because I know that gcc uses the fs segment for thread local variables. It should had generated something like
mov %rsp, fs:somevalue
which it is not. Why is that so? Is using thread local variables in inline assembly problematic?
A simple thing that would surely work is to take a pointer to the thread local variable, and write to it.
Your compiler will surely do long *saved_fp_p = &saved_fp correctly, and inline assembly will only deal with saved_fp_p, which is a local variable.
You can also use gcc's input and output syntax:
__asm__ __volatile__ (
"mov %%rsp, 0(%0)" : : "r" (&saved_sp)
);
This puts the compiler in charge of resolving the address of saved_fp, and the assembly code gets it in a register.
We found out that this also works,
__asm__ __volatile__ asm ("mov %rsp,%0" : "=m" (saved_sp))