1

I need to run this simple inline assembly code:

#include <stdio.h>

int count;

int main() {

  count = 0;
  for (int i = 0; i < 10; i++) {
    asm volatile ("incl count");  // count++
  }

  printf("count=%d\n", count); 

  return 0;
}

It works fine (printing count=10) until I turn on optimization (gcc -O1), in which case it prints count=0. I read that the "volatile" qualifier will prevent the optimizer to put the code out of loop. But it seems to have no effect here.

2
  • 1
    The GCC manual strongly urges you not to do this (accessing global variables by name in inline assembly). You should pass variables through input and output constraints. Something like asm ("incl %0" : "+rm"(count)); should work whether count is a local or global variable . The manual states Accessing data from C programs without using input/output operands (such as by using global symbols directly from the assembler template) may not work as expected. Commented May 8, 2018 at 17:08
  • 1
    If you look at the generated code (for example using -S), you'll see that gcc hasn't pulled the asm out of the loop. It's still invoking it 10 times. However, since gcc has ZERO visibility of what is happening in the asm statement, it has no reason to assume count is being affected, so the optimizer is free to assume it never changes from the initial value of 0. From the docs: GCC does not parse the assembler instructions themselves and does not know what they mean or even whether they are valid assembler input. Commented May 8, 2018 at 20:34

1 Answer 1

-3

Problem found. I had to define the global variable "count" as volatile. The problem was not putting asm block out of the loop. The compiler simply replaced count with 0 in printf.

volatile int count;

int main() {

  count = 0;
  for (int i = 0; i < 10; i++) {
    asm volatile ("incl count");  // count++
  }

  printf("count=%d\n", count); 

  return 0;
}
4
  • That's not the real problem (and not a proper solution), the real problem is, that you are using inline assembly incorrectly, see Michael's comment under question.
    – Ped7g
    Commented May 8, 2018 at 17:13
  • It might not be a good solution. But in this case, that really was the problem. I looked at the assembly code generated after compiler optimization. To call printf it had an instruction pushl 0 to push the argument, instead of pushl count after defining count as volatile it printed count=10
    – Behrooz Ns
    Commented May 8, 2018 at 17:20
  • 2
    yes, you got working code for now, but your fix is not fix, it will break eventually, if you will try to create something more complex and fix it in the same way. Besides that the volatile will kill the C parts completely. It's completely confusing me, why you are pushing these tools somewhere where they shouldn't work, and are in docs recommended to not push them like that, why don't you write rather pure assembly functions if you want to learn assembly, which is much easier than learning assembly and on top of that also learning the gcc inline assembly rules, which are far from trivial.
    – Ped7g
    Commented May 8, 2018 at 19:13
  • 1
    Or, in much worse case, you are actually trying to create some performance optimization of some C code... now your approach is somewhat valid for learning assembly (I just think it's too much and too mess, would suggest to work with asm only at first, then to learn inline rules). But if you are after performance, your current solution is completely wrong, going in opposite direction. Rather use C ++count;, it will end better (faster, shorter, etc..).
    – Ped7g
    Commented May 8, 2018 at 19:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.