为什么编译器可以假设全局变量的地址适合32位?

在查看这个简单函数的汇编程序(参见godbolt.org )时

extern int global; void doit(int *); void call_doit(){ doit(&global); } 

32位值用于保存global地址:

 call_doit: movl $global, %edi jmp doit 

据我所知,这里使用32位寄存器(即%edi )优于64位寄存器(即%rdi ),因为可以保存2个字节( movl $global, %edi需要5个字节而movq $global, %rdi需要7个字节+ 4个额外字节,如果不假设$global适合32位)。

(编者注:编译器实际上使用7字节lea global(%rip), %rdi来创建一个来自RIP + 32位相对位移的64位地址,编译器可以假设它在范围内有相关原因。并且movabs $global, %rdi对于64位绝对地址movabs $global, %rdi为10个字节,而不是11个。)

但是为什么编译器允许假设全局变量的地址适合这32位? 编译器有什么保证?


对于局部变量,编译器使用64位寄存器来保存堆栈地址,例如:

 void doit(int *); void call_doit(){ int local=0; doit(&local); } 

结果(见godbolt.org ):

 call_doit: subq $24, %rsp leaq 12(%rsp), %rdi movl $0, 12(%rsp) call doit addq $24, %rsp ret