Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is `and esp,0xfffffff0`?

When I disassemble a main() in gdb it retuns this result:

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

and in the code I examine esp register like this:

x/32xw $esp

and it makes this:

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

I want to know what's the relation between and esp,0xfffffff0 and these results.

like image 304
kerlinux Avatar asked Feb 12 '15 08:02

kerlinux


2 Answers

and esp,0xfffffff0 enforces 16 byte stack alignment, which is a common ABI requirement. It does this by masking out (setting to zero) the least significant 4 bits of the stack pointer, which is equivalent to rounding down to the nearest multiple of 16.

like image 156
Paul R Avatar answered Oct 13 '22 19:10

Paul R


It creates a so called stack frame and aligns it to addresses which can be divided by 16:

  1. Save stackframe pointer from calling programm in stack:
    push ebp.
  2. Create new stackframe pointer for the program which is called:
    mov ebp, esp
  3. Align stack to addresses which can be divided by 16 by setting the lowest 4 bit to 0:
    and esp, -16
  4. Create 16 byte space in stack for example for local variables and stuff:
    sub esp, 0x10

Why align?
The cpu always reads 16 bytes of data at once (depends on cpu type). But it reads only from an address which can be divided by 16: 0x0, 0x10, 0x20,.... And so on, because the lowest 4 bit are not used in the address bus. They are "missing". When you read more than a byte from an address, the cpu may have to read twice, because your address is directing to a dword or sth like that, that is right at the end of one address which can be divided by 16 and your dword reaches already into the next address divideable by 16. By aligining the stack to addresses which are divideable by 16, you reduce the risk of that happening, when working with the stack.

You can see that in the sample you posted. The value of ESP is on the left and aligned to addresses divideable by 16. Easy to see because of the ending 0:

0xbffffb70: 
0xbffffb80: 
0xbffffb90: 
0xbffffba0: 
0xbffffbb0: 
0xbffffbc0: 
0xbffffbd0: 
0xbffffbe0:
like image 21
Blechdose Avatar answered Oct 13 '22 20:10

Blechdose