Inline assmbler in C function

Hi,
I have been working on getting a C function with inline assembler to run, but with very little success.
It is very difficult to understand the syntax for this type of code but I think I finally understand at least part of it. However if I try to use indirect (indexed) addressing in my assembler code, strange things happen.
If I use a static declared variable for the address it works, but if I use a local variable for the address the address is extracted from the SP (and I guess that is correct) but it is completely wrong.

This example is working:

UINT32_t          os_sub(UINT32_t tmp0, UINT32_t tmp1, UINT32_t tmp2, UINT32_t tmp3)
{
  UINT32_t            asm_out;
  static UINT32_t   tmp3_loc = 0x1000;
  static UINT32_t*  tmp3_adr;

  tmp3_adr = &tmp3_loc;

  asm volatile
  (
    "nop\n\t"

    "MOV %1,%1\n\t"
    "ADD %0,%1,%2\n\t"
    "ADD %0,%0,%3\n\t"
    "MOV %4,%4\n\t"
    "LDR %4,[%4]\n\t"
    "ADD %0,%0,%4\n\t"

    "nop\n\t"

    : "=r"(asm_out)     /* related to %0 */
    : "r"(tmp0),        /* related to %1 */
      "r"(tmp1),        /* related to %2 */
      "r"(tmp2),        /* related to %3 */
      "r"(tmp3_adr)  /* related to %4 */
  );

  /* Needed for halting debug before return */
  asm_out += 0x10000000;

  return(asm_out);
}

And this is not:

UINT32_t          os_sub(UINT32_t tmp0, UINT32_t tmp1, UINT32_t tmp2, UINT32_t tmp3)
{
  UINT32_t            asm_out;
  UINT32_t            tmp3_loc = 0x1000;
 UINT32_t*           tmp3_adr;

  tmp3_adr = &tmp3_loc;

  asm volatile
  (
    "nop\n\t"

    "MOV %1,%1\n\t"
    "ADD %0,%1,%2\n\t"
    "ADD %0,%0,%3\n\t"
    "MOV %4,%4\n\t"
    "LDR %4,[%4]\n\t"
    "ADD %0,%0,%4\n\t"

    "nop\n\t"

    : "=r"(asm_out)     /* related to %0 */
    : "r"(tmp0),        /* related to %1 */
      "r"(tmp1),        /* related to %2 */
      "r"(tmp2),        /* related to %3 */
      "r"(tmp3_adr)         /* related to %4 */
  );

  /* Needed for halting debug before return */
  asm_out += 0x10000000;

  return(asm_out);
}

Am I doing something wrong or?

Regards

Sorry, I’m of no help here, but I agree 100% with what you say.

I’m currently writing a book on Arduino Assembly Language and inline assembly was something I looked into attempting to explain. Suffice to say, it was eventually dropped from the book!

Good luck with your problem.

Cheers,
Norm.

Reading https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html in regards to the clobber arguments

“memory”

The “memory” clobber tells the compiler that the assembly code performs memory reads or writes to items other than those listed in the input and output operands (for example, accessing the memory pointed to by one of the input parameters).

Adding that, you will see with Godbolt that it now loads the value 0x1000 (=4096) properly into the register and then saves it to the stack of the function (SP + 4). It then generates a pointer to the stack variable by computing SP + 4.

Is that what you mean?

1 Like

Excellent,
With the added clobber “memory” the code works.
I guess that the clobber “cc” is good to have.
ARM assembler is very tricky and I had a lot of strange things happening in my assembler code but now it is more predictable.
Thank you very much!
Regards

2 Likes