I’m able to use exported variables in assembly that is in a .S files. However, if I try to use exported variables in inline assembly it only works If the variable is modified in a zig function somewhere. Take this very simple example:
The above code will fail to build error: ld.lld: undefined symbol: my_exported_int However, if I modify my_exported_int in main before calling foo then it will build without issue.
My assumption is that zig doesn’t see my_exported_int used anywhere and optimizes it away. But, when I put the assembly code is in a .S files then it doesn’t matter if my_exported_int is modified or not in a zig function. The program will compile properly. Adding .extern my_exported_int to the inline assembly doesn’t change anything though it is obviously needed in the .S file.
Is it illegal to use exported variables in inline assembly?
I think this has more to do with Zig not being able to understand the assembly. Zig by default removes anything that is not referenced, and an assembly block is opaque to Zig ATM (it just passes the assembly off to clang).
However you can make this work better by passing the exported variable as an input to the asm block, something like this:
However I am unable to confirm if this compiles, because I can’t get your original code snippet to compile. (Hint: it might be easier for me to reproduce if you specify what system you are targeting, which is especially relevant when working with assembly)
I did try using the input constraints for the inline assembly but I ran into a different issues with that. In my actual assembly implementation the first thing I need to do is disable all interrupts. With arm cortex m its just a single instruction: CPSID I However, if I use inputs to the assembly block the inputs get loaded into the cpu registers before the instruction to disable interrupts is executed. Exporting the variables and manually loading them into the registers gives me the control over the assembly that I need and it works well in the .S file, but I’d really prefer to have the assembly in a .zig file instead of a .S file.
So, I have an interesting revelation about this issue. I’ve been working on this on and off since my last post and I’ve discovered something quite strange.
Firstly, I made a new blank project to test out my example as I previously made my example code in my preexisting project. To my surprise the example built without issue just like it did for @geemili. To make a long story short, I eventually got my new example project to produce the compile error by adding my assembly file that contains the start up code to the project.
In the assembly file there is a function named Rest_Handler. Reset_Handler eventually executes branch to main() instruction and that branch instruction causes the undefined symbol compile error. If I comment out the branch to main instruction the project will build as expected. I have no idea why this is the case. I can only assume that it is a bug in the zig compiler.