Salem beat me to it, but I'll post the example anyway:
demoaddress.c:
Code:
#include <stdio.h>
int g_i = 1337;
int main(void)
{
int i;
i = 5;
g_i = 10;
printf("i = %d\n",i);
printf("g_i = %d\n",g_i);
return 0;
}
Having MinGW spit out the assembly... demoaddress.s:
Code:
.file "demoaddress.c"
.globl _g_i
.data
.align 4
_g_i:
.long 1337
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "i = %d\12\0"
LC1:
.ascii "g_i = %d\12\0"
.text
.p2align 4,,15
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl $16, %eax
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
call __alloca
call ___main
movl $LC0, (%esp)
movl $10, %edx
movl $5, %eax
movl %edx, _g_i
movl %eax, 4(%esp)
call _printf
movl $LC1, (%esp)
movl _g_i, %eax
movl %eax, 4(%esp)
call _printf
leave
xorl %eax, %eax
ret
.def _printf; .scl 3; .type 32; .endef
i is never mentioned in the assembly code because it's a local variable and on the stack. That's how the compiler knows the address of that one.
For the global variable g_i, you can see it's referenced by name. By the time it gets to the exe, however, all references to g_i are no longer by name. Because it's global, it's put right into the application itself, and the address assigned it by the linker is set at that time.
Consider this line in C:
This is how GCC translated that into assembly:
Code:
movl $10, %edx
...
movl %edx, _g_i
Salem's explanation is the key here to understanding this. When the linker goes through the assembly code to make an exe, it'll change the assembly reference to _g_i to something like 0x40302092 (I chose a random address, but the process is not random.) or as Salem suggested, 0x1234. Date will be moved to and from the spot the address refers to. When you write &g_i in C code, it'll just result in 0x40302092 (or whatever address the linker set it to). Doing &&g_i doesn't make much sense. You won't get anything meaningful.