Iroha
Iroha

Reputation: 51

Using Assembler in C without using placeholders

I've been assigned a task that's theoretically not too hard. A C variable should be changed by using Assembler code (asm). I've done this and it works, but the second part of the assignment is to do the same thing WITHOUT using placeholders (%).

I'm at a loss here and after some research I have still not found a solution. How can I access or maniplate C variables in assembler code without using placeholders to get the variable?

Here's the code with placeholders:

    volatile uint8_t number = 1;
    volatile uint8_t *number_pointer = &number;

    asm volatile(
        "ld r20, %a0" "\n\t"
        "lsl r20" "\n\t"
        "st %a0, r20" "\n\t"
        "breq resetten" "\n\t"
        "ret" "\n\t"

        "resetten:" "\n\t"
        "ldi r20, 1" "\n\t"
        "st %a0, r20"
          : "+e" (number_pointer)
    );

In short: How can I access and change "number_pointer" without using a %? (The code doubles "number" until it is 128, then it starts with 1 again.)

Upvotes: 5

Views: 499

Answers (1)

akruppa
akruppa

Reputation: 41

To comment on Davids suggestion (I would post this as comment if I had enough reputation): use the "memory" hint in the clobbered field, like in asm("nop":::"memory");

This tells gcc that the asm statement modifies memory and that variables need to be re-loaded, etc.

For example, with

static int foo;
int bar()
{
  foo = 1;
  __asm__("":::"memory");
  return foo;
}

we get

Dump of assembler code for function bar:

   0x0000000000000000 <+0>:         movl   $0x1,0x0(%rip)        # 0xa <bar+10>
   0x000000000000000a <+10>:        mov    0x0(%rip),%eax        # 0x10 <bar+16>
   0x0000000000000010 <+16>:        retq   

whereas without the "memory", the re-load of the variable value is missing.

Upvotes: 1

Related Questions