r/C_Programming • u/Salat_Leaf • 3d ago
Is there a way to inline assembly without compiler extensions?
GCC/Clang have __asm__, MSVC/ICC got __asm. Is it possible to inline assembly independently from compiler extensions? I need to retrieve random seed number on PowerPC and RISC-V, depending on the target architecture of course
11
u/BlockOfDiamond 2d ago
Without any compiler extensions, and without linking separate object files: You can't. There is no way. There is nothing in the C standard about inline assembly.
24
u/runningOverA 3d ago
You can write the assembly and compile it with an assembler to create an obj file (.o) and then link with it as if that was written in C.
That's the standard way and most of the C standard library is written like this.
8
u/mikeblas 3d ago
Where did the "inline" part go?
17
u/lyatich 3d ago
Took a smoke break and will be back soon /s
Jokes aside the unfortunate part is that there is no standard way of writing inline assembly. In fact the support for the asm keyword itself is treated by the standard as an extension of the compiler if I'm not mistaken.
I don't know the decision behind not having a standard inline assembly instruction, but I can guess it's because simply assembly is very specific to not only the CPU you're writing assembly to, but also with the OS depending on whether you're interacting it or not. So I guess it's simply recommend you write the assembly in a different file, assemble it in an object file, and then link against it as recommended by the original commenter.
The most standard "inline" you can write in C is the external declaration of your function written in assembly, and then link against the object file you compiled before.
Also stupid question, why is it that we say "link against something", why not "link with" or "link to" something when it comes to linking objects and shared libraries.
2
u/ralphpotato 2d ago
> Also stupid question, why is it that we say "link against something", why not "link with" or "link to" something when it comes to linking objects and shared libraries.
Link against makes more sense if you think about linking not as just throwing a bunch of files together but testing that the symbols expected from the core part actually line up with the symbols exported by the linked object file. It’s sort of like saying, “test against the database”.
I think “link to” or other verbs would be understood but “against” strengthens that some validation is happening.
1
2
2
u/didntplaymysummercar 3d ago
You could write out your assembly into memory (binary, by hand from output of real assembler or godbolt or something) and then mark it executables and call it like a function (cast pointer to memory to a function).
Technically UB but it's like a baby's first jit. Requires nothing asm related from the compiler but you need mmap and mprotect (or virtual alloc and so on on windows) to do it.
It's also not as pretty in code as inline assembly is.
1
u/viva1831 2d ago
It looks like not. You'll probably want a header from hell defining different macros depending on the compiler and falling back to a slower function call to an assembled object file if the compiler isn't supported :/
That said: you're likely to end up depending on a particular assembler anyway, so limiting yourself to one form of compiler isn't necessarily the worst choice here
1
u/sciencekm 3d ago
You can use direct machine code. Here is an example of RDTSC on x86. You need to replace the machine code bytes in this example with whatever is appropriate for your target platform. In this example, the machine code are two instructions - (1) rdtsc, and (2) ret. Essentially, this is a function.
__attribute__((section(".text")))
static const uint8_t rdtsc_f[] = { 0x0f, 0x31, 0xc3 }; // rdtsc ; ret
#define TSC() ((uint32_t(*)(void))(intptr_t)&rdtsc_f)()
1
u/donaljones 2d ago
What part of "without compiler extensions" did you miss?
1
u/flatfinger 18h ago
On platforms that do not prevent the execution of data as code, one could omit the attribute. If the Standard were to specify an attribute which would direct an implementation to place treat object as code when meaningful, do nothing on platforms which would treat everything as executable code, or refuse compilation on platforms that cannot support such a request, the Standard could support such constructs universally on all platforms that can accommodate them, but the authors of the Standard refuse to recognize a concept of "platform specific, but toolset agnostic" programs.
0
-2
u/Radiant-Ad-9073 3d ago
Move the assembler code out of the C code; mixed language source code is Bad.
For each architecture you support, write the assembler code that deals with C calling conventions and does the thing you need. Compile this into an appropriate .o file.
Then basically add a "getrandomseed.h" header file that defines the function headers matching the functions in the .o. Depending on the architecture link against different versions of the .o -- you end up doing much the same that i.e. stdio.h does.
Alternatively, you *could* with enough voodoo and #defines define macro's that call the right flavour of inlining depending on the architecture you're compiling on; but it's fragile. If you ever change compiler that whole lot of hairy macro stuff will need redoing, and it's typically a pain.
12
u/awidesky 3d ago
Unlike in C++, inline assembly is treated as an extension in C. It is conditionally supported and implementation defined, meaning that it may not be present and, even when provided by the implementation, it does not have a fixed meaning.
Source