If I compile this program:
#include <stdio.h>
int main(int argc, char** argv) {
    printf("hello world!\n");
    return 0;
}
for x86-64, the asm output uses movl  $.LC0, %edi / call puts.  (See full asm output / compile options on godbolt.)
My question is: How can GCC know that the the string's address can fit in a 32bit immediate operand?  Why doesn't it need to use movabs  $.LC0, %rdi (i.e. a mov r64, imm64, not a zero or sign-extended imm32).
AFAIK, there's nothing saying the loader has to decide to load the data section at any particular address.  If the string is stored at some address above 1ULL << 32 then the higher bits will be ignored by the movl.  I get similar behavior with clang, so I don't think this is unique to GCC.
The reason I care is I want to create my own data segment that lives in memory at any arbitrary address I choose (above 2^32 potentially).
 
     
     
     
    