which generates kind of not expected assembly, it moves the value of the variable to rsp + 08, then stores the pointer to rsp + 08 to rsp, then tries to jmp [rsp], so it would be jumping to the address of rsp + 08Compiler Explorer
and I don’t want to use “r” input constraint i would like to avoid using any general purpose registers.
I don’t get it lea rax, [rsp + 8] supposed to store the address of rsp+8 to rax right? then this rax gets stored to [rsp] so when jmp [rsp] happens its going to read the address of rsp+8, at least that’s what’s my debugger is showing what’s happening
Start
rax: undefined
[rsp]: undefined
[rsp + 8]: undefined
mov rax, qword ptr [example.do_something_trampoline]
rax: value of do_something_trampoline
[rsp]: undefined
[rsp + 8]: undefined
mov qword ptr [rsp + 8], rax
rax: value of do_something_trampoline
[rsp]: undefined
[rsp + 8]: value of do_something_trampoline
lea rax, [rsp + 8]
rax: address of rsp + 8
[rsp]: undefined
[rsp + 8]: value of do_something_trampoline
mov qword ptr [rsp], rax
rax: address of rsp + 8
[rsp]: address of rsp + 8
[rsp + 8]: value of do_something_trampoline
jmp qword ptr [rsp]
This will jump to address of rsp + 8,
but we should be jumping to do_something_trampoline
then the whole thing doesn’t make sense, it’s loading the value to rax from the variable address, then storing it to rsp + 8 then again reloading it to rax, lea rax,[rsp+8]
Probably completely off topic, sorry sorry.
In the far past I did quite some assembly in Delphi.
When I see the asm syntax we need in Zig I am kinda confused.
Why these superweird stuff and not just some asm block with real statements?
Assembly is a block box for the compiler, so it would have to disable all optimizations when it finds one. Constraints are a way to recover some optimizations. You tell the compiler what you’re reading and writing, and it ensures that the assembly block is properly ordered according to the statements around it. Without that, the compiler could reorder the statements in such a way that you could be reading a value that wasn’t computed yet, or your write could be overwritten.
Constraints are not optional, reading or writing values without setting the proper constraints is undefined behavior.
needs export var do_something_trampoline: usize = 0; for it to compile kinda weird? is it fixed in some newer version? or whatever https://godbolt.org/ is using?
That’s intended. My bad, I forgot about export.
Godbolt only runs the compilation phase, it doesn’t do linking, which is way it didn’t error.
You can avoid the export by doing this:
The body of an inline assembly is a separate compilation unit, so it can only access things that are exported, or that explicitly provided to it in the constraints. "rmx" is explained here.
Concatenating constraints by juxtaposition like this means an alternative. r is register, m is memory, and x is supposed to be “anything”. The compiler can choose to pass the value of do_something_trampoline to the body of the inline assembly in any of these places. You’d imagine that x would make everything else redundant, but, for some reason, it doesn’t.
I tried each individual constraint and neither one generated the desired assembly, only when I provided all the alternatives.