Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.)

like image 780
Iroha Avatar asked Nov 11 '22 08:11

Iroha


1 Answers

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.

like image 114
akruppa Avatar answered Nov 15 '22 09:11

akruppa