Here is a simple C code
#include <stdio.h>
int a = 5;
static int b = 20;
int main(){
 int c = 30;
 return 0;
}
Compiled to assebly with no optimization:
    .section    __TEXT,__text,regular,pure_instructions
    .macosx_version_min 10, 13
    .globl  _main                   ## -- Begin function main
    .p2align    4, 0x90
_main:                                  ## @main
    .cfi_startproc
## %bb.0:
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register %rbp
    xorl    %eax, %eax
    movl    $0, -4(%rbp)
    movl    $30, -8(%rbp)
    popq    %rbp
    retq
    .cfi_endproc
                                        ## -- End function
    .section    __DATA,__data
    .globl  _a                      ## @a
    .p2align    2
_a:
    .long   5                       ## 0x5
My question is where is static int b = 20; in the above assembly?
I know they are supposed to be in the global section of the memory but I cannot find it in the compiled version.
Your code doesn't use b, and it's file-scoped so nothing in other files can use it.  GCC doesn't bother to emit a definition for it.
To answer  the title question:
A non-const static / global variable (i.e. static storage class) variable with a non-zero initializer will go in .section .data, as opposed to .bss (zero-init mutable), or .rdata (Windows) / .rodata (Linux) for non-zero read-only data.
gcc doesn't have a fully braindead mode that transliterates to asm naively. See Disable all optimization options in GCC - GCC always has to transform through its internal representations.
GCC always does a pass that leaves out unused stuff even at -O0.  There might be a way to disable that, unlike some of the other transformations gcc does even at -O0.
gcc and clang -O0 compile each statement to a separate block of asm that stores/reloads everything (for consistent debugging), but within that block gcc still applies its standard transformations, like (x+y) < x becoming y<0 for signed x and y with gcc8 and newer, or x / 10 into a multiply + shift of the high half.  (Why does GCC use multiplication by a strange number in implementing integer division?).
And code inside if(false) is removed by gcc even at -O0, so you can't jump to it in GDB.
Some people care about runtime performance of debug builds, especially developers of real-time software like games or operating systems that's not properly testable if it runs too slowly. (Human interaction in games, or maybe device drivers in OSes.)
Some other compilers are more braindead at -O0, so you do often see asm that looks even more like the source expressions.  I think I've seen MSVC without optimization emit instructions that did mov-immediate into a register, then cmp reg,imm, i.e. do a branch at runtime that only depends on immediate, and thus could trivially have been computed at compile time within that expression.
And of course there are truly non-optimizing compilers whose entire goal is just to transliterate with fixed patterns.  For example, the Tiny C Compiler I think is pretty much one-pass, and emits asm (or machine code) as it goes along.  See Tiny C Compiler's generated code emits extra (unnecessary?) NOPs and JMPs shows just how simplistic it is: it always emits a sub esp, imm32 in function prologues, and only comes back to fill in the immediate at the end of the function once it knows how much stack the function needs.  Even if the answer is zero, it can't remove it and tighten up the code.
It's usually more interesting to look at optimized asm anyway. Write functions that take args and return a value, so you can see the interesting part of the asm without a lot of boilerplate and store/reload noise. How to remove "noise" from GCC/clang assembly output?
If a static variable hasn't been optimized out by the compiler, it will go in the process' default data section.
In assembly, that can normally be controlled by the programmer in a section of the file designated for describing the data section.
The C Standard says in § 6.2.4 paragraph 3:
An object whose identifier is declared ... with the storage-class specifier static, has static storage duration. Its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.
With the following code:
static int a = 100;
int foo()
{
    return (a / 2);
}
Look at how the symbol _a appears in the _DATA segment for MSVC, lines 27-30 for GCC, and lines 28-30 for Clang.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With