2

I wrote a function in assembly and now I want to use it in C but my function is not for 'call' and 'ret' and the return address will be store in a register and in the function, we just jmp to that location (register) and there is no 'ret' so for executing this function in C, I just need to make a label for the function return address and load that label memory address into the 'rdx' and jmp to that assembly function, and then it's done so I designed this code

unsigned
calling_asm_func() {
    unsigned res;
    __asm__ __volatile__("jmp\tmy_asm_func" : "=a" (res) : "d" (&& result) : "rcx", "rdi", "rsi", "r8", "r9", "r10", "r11", "memory");
    result:
    return res;
}

it looks fine and it's ok but the generated assembly code is wrong !!!!!!!!

calling_asm_func:
.L2:
  mov edx, OFFSET FLAT:.L2
  jmp my_asm_func
  ret

.L2 Must be above of ret as you can see it in the C code what is the problem? How can I fix it?

It must be something like this:

calling_asm_func:
  mov edx, OFFSET FLAT:.L2
  jmpmy_asm_func
.L2:
  ret

See this on GodBolt with GCC 10.2

Also, it's funny ! With -O1 option, it's OK and there is no problem !!!!!!! But the problem is with -O2 and -O3 !!!

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
HelloMachine
  • 355
  • 2
  • 8
  • 1
    Adding a non-optimizable statement after the label fixes it too. Pretty sure this is an optimizer bug. Report it to GCC and get a cookie! – Anton Tykhyy Nov 02 '20 at 08:49
  • 2
    Note that your function must not clobber RDX because you told GCC it was a pure input. Perhaps you want a `"+d"()` input/output operand, or a matching input constraint for a dummy output. Also, your function must not clobber any XMM, MMX, or x87 registers because you didn't declare clobbers on them. – Peter Cordes Nov 02 '20 at 08:55
  • 1
    Your function also must not use any stack space because GCC assumes that `asm()` statements don't step on the red-zone below RSP, and there's no way to tell it you want to: [Inline assembly that clobbers the red zone](https://stackoverflow.com/q/6380992). You might consider `gcc -mno-red-zone` for this file (unfortunately doesn't work with per-function target attributes) – Peter Cordes Nov 02 '20 at 09:00
  • 1
    (Or to avoid the red zone, your asm statement could do `add rsp, -128` / `sub rsp, -128` before/after. -128 fits in an 8-bit signed immediate, +128 doesn't). – Peter Cordes Nov 02 '20 at 09:38
  • 1
    You can (kinda) change this to an asm goto statement (since it is one, right?). This seems to fix the problem. The bad news is that asm goto statements can't have outputs. Closest I can get is `__asm__ goto("mov %0, rdx\n\tjmp\tmy_asm_func" : : : "rax", "rcx", "rdi", "rsi", "r8", "r9", "r10", "r11", "memory" : result);` You could try putting `__asm__ volatile ("" : "=a"(res));` after `result`, but blech. You'd be depending on the compiler ordering statements the way you want, with no guarantee it will do so. – David Wohlferd Nov 02 '20 at 20:17
  • Couldn't you simply put the label inside the asm, and load its address yourself? `asm("lea 1f(%%rip), %%rdx ; jmp my_asm_func ; 1:" ...)` – Nate Eldredge Nov 18 '20 at 03:21

0 Answers0