2015-02-12 58 views
6

当我在gdb拆解main()它retuns这样的结果:'和esp,0xfffffff0'是什么?

0x0804854c <+0>: push ebp 
    0x0804854d <+1>: mov ebp,esp 
    0x0804854f <+3>: and esp,0xfffffff0 
    0x08048552 <+6>: sub esp,0x10 

,并在代码中,我考察esp寄存器:

x/32xw $esp 

,它使这个:

0xbffffb70: 0xb7ea1515 0xb7ff0590 0x080485eb 0xb7fd2ff4 
0xbffffb80: 0x080485e0 0x00000000 0xbffffc08 0xb7e88e46 
0xbffffb90: 0x00000002 0xbffffc34 0xbffffc40 0xb7fe0860 
0xbffffba0: 0xb7ff6821 0xffffffff 0xb7ffeff4 0x080482bc 
0xbffffbb0: 0x00000001 0xbffffbf0 0xb7fefc16 0xb7fffac0 
0xbffffbc0: 0xb7fe0b58 0xb7fd2ff4 0x00000000 0x00000000 
0xbffffbd0: 0xbffffc08 0xd51689cb 0xfbfdbfdb 0x00000000 
0xbffffbe0: 0x00000000 0x00000000 0x00000002 0x08048400 

我想知道and esp,0xfffffff0与这些结果之间的关系。

+0

堆栈指针对准性能方面的原因和调整后的数据acceess。 '和'本身在asm参考中解释。 – 2015-02-12 08:21:12

回答

0

显然and esp,0xfffffff0通过掩盖它删除最底层的esp半字节。

10

and esp,0xfffffff0执行16字节堆栈对齐,这是一个常见的ABI要求。它通过屏蔽掉(设置为0)堆栈指针的最低有效4位来实现这一点,相当于向下舍入到最接近的16的倍数。

6

它创建一个所谓的堆栈帧并将其对齐到地址从主叫PROGRAMM在堆

  1. 保存的StackFrame指针:其可以通过16被划分
    push ebp
    mov ebp, esp
  2. 对齐叠放到其可以通过16被划分通过设置最低4位为0的地址::
    and esp, -16
  3. 在创建16个字节的空间
  4. 为这就是所谓的程序创建新的StackFrame指针堆栈例如用于局部变量和东西:
    sub esp, 0x10

为什么对齐?
CPU总是一次读取16个字节的数据(取决于CPU类型)。但它只能从一个可以被16除的地址读取:0x0,0x10,0x20,....等等,因为地址总线中不使用最低4位。他们“失踪”。当你从一个地址读取多于一个字节时,CPU可能必须读两次,因为你的地址正在指向一个双字或者这样的字,这就是在一个地址的末尾,它可以被16除,而你的双字已经到达可以被16分隔的下一个地址。 通过将堆栈对齐到可被16分隔的地址,在使用堆栈时可以降低发生这种情况的风险。

您可以在您发布的示例中看到。 ESP的值是左对齐,并通过16易divideable地址看到,因为结束0的:

0xbffffb70: 
0xbffffb80: 
0xbffffb90: 
0xbffffba0: 
0xbffffbb0: 
0xbffffbc0: 
0xbffffbd0: 
0xbffffbe0: