Why is this simple c program with gcc (clang) inline assembly exhibiting undefined behaviour?

时光总嘲笑我的痴心妄想 提交于 2019-12-06 05:47:59

Your first code does not specify any inputs to the asm statements so the chosen register has an undefined value (which in this case was initially the return value of printf). The second example repeats the error of using an undefined value and adds further undefined behaviour by overwriting the input register with the output.

You could use two registers like:

__asm__ (
   "movq %1, %0 \n\t"
   "addq $1, %0"
   : "=r" (zero)
   : "r" (zero)
);

You could use an input/output argument:

__asm__ (
   "addq $1, %0"
   : "+r" (zero)
);

Which can be in memory as well as a register:

__asm__ (
   "addq $1, %0"
   : "+rm" (zero)
);

Or you could tie the input to the output:

__asm__ (
   "addq $1, %0"
   : "=rm" (zero)
   : "0" (zero)
);

And finally there is no need for any of the volatile modifiers.

To wrap it all up:

inline assembly is not the part of C standard, it's an extension so portability (even across compilers on the same hardware) is not guaranteed.

one good way to write it is following:

#include <stdio.h>
#include <stdint.h>
#define inf_int uint64_t
int main(int argc, char *argv[]){
   inf_int zero = 0;
   inf_int one = 1;
   inf_int infinity = ~0;
   printf("value of zero, one, infinity = %lu, %lu, %lu\n", zero, one, infinity);
   __asm__ (
      "addq $1, %0 \n\t"
      : "+r" (zero)
   );
   __asm__ (
      "addq $1, %0 \n\t"
      : "+r" (one)
   );
   __asm__ (
      "addq $1, %0 \n\t"
      : "+r" (infinity)
   );
   printf("value of zero, one, infinity = %lu, %lu, %lu\n", zero, one, infinity);
   return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!