为什么编译器可以假设全局变量的地址适合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