Int vs Double 汇编
Int vs Double in assembly
为什么 GCC 编译器在使用 double 时添加这三行,而在使用 Int 时不添加?
使用整数:
#include <cstdio>
int main(){
int i = 1;
}
==>
main:
push ebp
mov ebp, esp
sub esp, 16
mov DWORD PTR [ebp-4], 1
mov eax, 0
leave
ret
加倍:
#include <cstdio>
int main(){
double i = 1;
}
==>
main:
lea ecx, [esp+4] // This three lines
and esp, -8 // ...
push DWORD PTR [ecx-4] // ...
push ebp
mov ebp, esp
push ecx
sub esp, 20
fld1
fstp QWORD PTR [ebp-16]
mov eax, 0
add esp, 20
pop ecx
pop ebp
lea esp, [ecx-4]
ret
使用指针时会发生类似情况,例如 int *s = new int(4);
你能解释为什么会发生这种情况吗?为什么不总是这样?
如果 double
在自动范围内(在堆栈上),额外的代码将堆栈帧对齐到偶数 8 字节边界,因此 double
变量存储在具有适当对齐方式的内存地址。进入函数时,堆栈指针不能保证在偶数 8 字节边界上对齐,编译器会添加额外的代码来实现。
这就是 and esp, -8
的作用。 -8 是 0xFFFFFFF8。这将使用 and
清除 esp
的最后 3 位,使其指向偶数 8 字节边界内存地址,将其向下调整(堆栈从高内存地址增长到低内存地址)。
为什么 GCC 编译器在使用 double 时添加这三行,而在使用 Int 时不添加?
使用整数:
#include <cstdio>
int main(){
int i = 1;
}
==>
main:
push ebp
mov ebp, esp
sub esp, 16
mov DWORD PTR [ebp-4], 1
mov eax, 0
leave
ret
加倍:
#include <cstdio>
int main(){
double i = 1;
}
==>
main:
lea ecx, [esp+4] // This three lines
and esp, -8 // ...
push DWORD PTR [ecx-4] // ...
push ebp
mov ebp, esp
push ecx
sub esp, 20
fld1
fstp QWORD PTR [ebp-16]
mov eax, 0
add esp, 20
pop ecx
pop ebp
lea esp, [ecx-4]
ret
使用指针时会发生类似情况,例如 int *s = new int(4);
你能解释为什么会发生这种情况吗?为什么不总是这样?
如果 double
在自动范围内(在堆栈上),额外的代码将堆栈帧对齐到偶数 8 字节边界,因此 double
变量存储在具有适当对齐方式的内存地址。进入函数时,堆栈指针不能保证在偶数 8 字节边界上对齐,编译器会添加额外的代码来实现。
这就是 and esp, -8
的作用。 -8 是 0xFFFFFFF8。这将使用 and
清除 esp
的最后 3 位,使其指向偶数 8 字节边界内存地址,将其向下调整(堆栈从高内存地址增长到低内存地址)。