Home > Blockchain >  Non volatile global var works in loop
Non volatile global var works in loop

Time:08-19

  1 #include <stdio.h>
  2 #include <stdbool.h>
  3 
  4 bool flag;
  5 
  6 static void foo(int a, int b)
  7 {
  8     printf("why\n");
  9     return;
 10 }
 11 
 12 int main()
 13 {
 14 
 15     while (!flag) {
 16         foo(10, 11);
 17     }
 18 
 19     return 0;
 20 }

build with aarch64-linux-gnu-gcc -O2 t.c

objdump with aarch64-linux-gnu-objdump -Sdf a.out > t

 55 0000000000400460 <main>:
 56   400460:   a9be7bfd    stp x29, x30, [sp, #-32]!
 57   400464:   910003fd    mov x29, sp
 58   400468:   f9000bf3    str x19, [sp, #16]
 59   40046c:   b0000093    adrp    x19, 411000 <__libc_start_main@GLIBC_2.17>
 60   400470:   3940c660    ldrb    w0, [x19, #49]
 61   400474:   35000140    cbnz    w0, 40049c <main 0x3c>
 62   400478:   f9000fb4    str x20, [x29, #24]
 63   40047c:   9100c673    add x19, x19, #0x31
 64   400480:   90000014    adrp    x20, 400000 <_init-0x3e8>
 65   400484:   91198294    add x20, x20, #0x660
 66   400488:   aa1403e0    mov x0, x20
 67   40048c:   97fffff1    bl  400450 <puts@plt>
 68   400490:   39400260    ldrb    w0, [x19]
 69   400494:   34ffffa0    cbz w0, 400488 <main 0x28>
 70   400498:   f9400fb4    ldr x20, [x29, #24]
 71   40049c:   52800000    mov w0, #0x0                    // #0
 72   4004a0:   f9400bf3    ldr x19, [sp, #16]
 73   4004a4:   a8c27bfd    ldp x29, x30, [sp], #32
 74   4004a8:   d65f03c0    ret

my concern is why #68 always load flag from memory? it's not a volatile type, isn't it only load from mem one time then read from register? if I remove c code #16, there's no function call in loop, I can see it load flag from memory only one time.

it seems function call in loop do the magic.

any explanation on this?

CodePudding user response:

Because flag has external linkage and the compiler cannot assume that it won't get updated from another translation unit in the middle of execution.

Change flag to static or make it local and then the whole program will be replaced with an eternal loop calling puts over and over.


Edit: relevant disassembly from gcc 12.1 for ARM64 -O3 of the original code:

.L3:
        mov     x0, x20
        bl      puts
        ldrb    w0, [x19]
        cbz     w0, .L3

Changing flag to static creates an eternal loop:

.L2:
        mov     x0, x19
        bl      puts
        b       .L2

Keeping flag as extern linkage but commenting out the function call:

.L3:
        b       .L3

The last one happens since the loop body no longer contains no side effects such as printing, if the function call is removed. It is then pointless to check the variable.

  • Related