Why is the address of static variables relative to the instruction pointer?

I follow this build tutorial .

According to the tutorial (which I also tried locally and got similar results), the following source code:

int natural_generator()
{
        int a = 1;
        static int b = -1;
        b += 1;              /* (1, 2) */
        return a + b;
}

Compiles these assembly instructions:

$ gdb static
(gdb) break natural_generator
(gdb) run
(gdb) disassemble
Dump of assembler code for function natural_generator:
push   %rbp
mov    %rsp,%rbp
movl   $0x1,-0x4(%rbp)
mov    0x177(%rip),%eax        # (1)
add    $0x1,%eax
mov    %eax,0x16c(%rip)        # (2)
mov    -0x4(%rbp),%eax
add    0x163(%rip),%eax        # 0x100001018 <natural_generator.b>
pop    %rbp
retq   
End of assembler dump.

(Added line numbers (1), (2)and (1, 2)).

Question : why in the compiled code is the address of a static variable brelative to the instruction pointer (RIP), which is constantly changing (see lines (1)and (2)) and, therefore, generates more complex assembler code, and does not refer to a specific section of the executable file where such variables are stored?

, :

, b , .

( .)

+4
1

, RIP- b. -, , , , . -, 64- , 8- (64-) , , 64- x86.

, , , . , , . . , , . , b ( ) .

32- x86 RIP, - , 32- . b (GOT), GOT. , gcc -m32 -O3 -fPIC -S test.c:

natural_generator:
        call    __x86.get_pc_thunk.cx
        addl    $_GLOBAL_OFFSET_TABLE_, %ecx
        movl    b.1392@GOTOFF(%ecx), %eax
        leal    1(%eax), %edx
        addl    $2, %eax
        movl    %edx, b.1392@GOTOFF(%ecx)
        ret

ECX. GOT GOT . ECX GOT b .

64- , gcc -m64 -O3 -S test.c:

natural_generator:
        movl    b.1745(%rip), %eax
        leal    1(%rax), %edx
        addl    $2, %eax
        movl    %edx, b.1745(%rip)
        ret

( , . , , , . , -fPIC , 64- .)

, 64- , . , (ECX). , , - . , .

+6

Source: https://habr.com/ru/post/1659325/


All Articles