2015-02-12 78 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: