C 为什么编译器可以假设全局变量的地址适合32位?
当查看此简单函数的汇编程序(请参见上)时C 为什么编译器可以假设全局变量的地址适合32位?,c,gcc,x86-64,C,Gcc,X86 64,当查看此简单函数的汇编程序(请参见上)时 extern int global; void doit(int *); void call_doit(){ doit(&global); } 32位值用于保存全局的地址: call_doit: movl $global, %edi jmp doit 我理解,在这里使用32位寄存器(即%edi)优于64位寄存器(即%rdi),因为可以保存2个字节(movl$global,%edi需要5个字
extern int global;
void doit(int *);
void call_doit(){
doit(&global);
}
32位值用于保存全局
的地址:
call_doit:
movl $global, %edi
jmp doit
我理解,在这里使用32位寄存器(即%edi
)优于64位寄存器(即%rdi
),因为可以保存2个字节(movl$global,%edi
需要5个字节,而movq$global,%rdi
需要7个字节+4个额外字节,如果不假设$global
适合32位的话)
(编者按:编译器实际上使用7字节leaglobal(%rip),%rdi
从rip+32位相对位移创建64位地址,编译器可以根据相关原因假设该地址在范围内。对于64位绝对地址,movabs$global,%rdi
将是10字节,而不是11字节。)
但是为什么编译器可以假设全局变量的地址适合这32位呢?编译器有什么保证
对于局部变量,编译器使用64位寄存器保存堆栈地址,例如:
void doit(int *);
void call_doit(){
int local=0;
doit(&local);
}
结果(请参见上的):
有趣。C要求编译器能够在一个翻译单元中处理至少4095个不同的标识符,但没有提到链接整个程序。GNU链接器施加并依赖的全局标识符的数量是否有限制?@mhc这是因为尾部调用优化仅在第一种情况下可能(在第二种情况下,您必须调整%rsp)顺便说一句,如果您创建的程序具有超过4GB的全局变量,你做错事的概率不是零可能32位是.data和.bss段的限制。即使是Clang和ICC也会为全局情况生成32位移动。如果您更改为C++,您将有更多的编译器进行测试,而在这些ZAPCC和ELCC中,也会发出<代码> MOVL$Global,%EDI
call_doit:
subq $24, %rsp
leaq 12(%rsp), %rdi
movl $0, 12(%rsp)
call doit
addq $24, %rsp
ret