6

I am using Rust to target a baremetal system. My startup code is written in Assembly and is in crt0.S, it is shared between Rust, C and Assembly projects.

crt0.S contains:

#include "constants.h"  
li a0, A_CONSTANT  

When building crt0.S as part of a C program, the preprocessor runs and substitutes a value for A_CONSTANT.

This does not happen in Rust, but I can use bindgen then substitute the value in global_asm

include!(concat!(env!("OUT_DIR"), "/bindings.rs"));  
global_asm!(include_str!("crt0.S"), A_CONSTANT = const A_CONSTANT);  

However, I then need to write crt0.S like this, which won't compile in C/asm

li a0, {A_CONSTANT} 

Is there some way I can write the line in crt0.S which will work for both?

How about moving your constants into some .inc file written in assembly like A_CONSTANT .equ 1234 and then include it using .include directive?

Then I won't be able to use the constants from C code. I also need them from code which does not link with the assembly.

10
  • Which compiler are you using and for what target? Inline asm isn't standardized and will differ between compilers and targets. Commented Dec 8 at 8:51
  • 1
    @TobyJaffey Put the answers to questions you get in the comment section in your question instead of answering in the comment section. Commented Dec 8 at 14:41
  • 1
    Process the assembly file with the C preprocessor (e.g., gcc -E or clang -E) before assembling it. Commented Dec 8 at 15:41
  • 1
    Re “This does not happen in Rust” and “won't compile in C/asm”: There is no such thing as “C/asm”, and it is not Rust this is happening in. It is happening in your build system. Your build system and your various projects may be configured to set various defaults for how they process assembly files that were added to a project initially created with a “C” or “Rust” template, but those defaults are almost certainly changeable. Commented Dec 8 at 15:44
  • 3
    "Shared assembly" seems to be either a poor characterization or just a poor idea. Assemble your assembly code directly, with an assembler, then link the resulting object file to whatever program you need to link it to. Compile your C code with a C compiler and your Rust code with a Rust compiler -- the assembly need not be shared between them or with either one, other than by linking. Providing for a collection of common symbols for constants that they all reference is a reasonable objective, but it is not well suited to be addressed as a code sharing problem. Commented Dec 8 at 16:55

1 Answer 1

4

The simplest working solution I have is:

#include "constants.h"
#if 1
// rust will interpret the "#if 1" and "#include" as comments and ignore
// gcc, gnu as, zig will include the file below, which references a constant from constants.h
#include "non-rust-crt0-hack.S"
#else
// only rust will see this and will substitute the value via bindgen of "constants.h"
li a0, {A_CONSTANT}
#endif

Then, in non-rust-crt0-hack.S:

li a0, A_CONSTANT

It's not pretty, but I still have a single source of truth in constants.h. I do have to repeat the assembly instruction in the second file, but there is no risk of the constant getting out of step.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.