Assume the stack looks like this on entry to _main
(the address of the stack pointer is just an example):
| existing |
| stack content |
+-----------------+ <--- 0xbfff1230
Push %ebp
, and subtract 8 from %esp
to reserve some space for local variables:
| existing |
| stack content |
+-----------------+ <--- 0xbfff1230
| %ebp |
+-----------------+ <--- 0xbfff122c
: reserved :
: space :
+-----------------+ <--- 0xbfff1224
Now, the andl
instruction zeroes the low 4 bits of %esp
, which may decrease it; in this particular example, it has the effect of reserving an additional 4 bytes:
| existing |
| stack content |
+-----------------+ <--- 0xbfff1230
| %ebp |
+-----------------+ <--- 0xbfff122c
: reserved :
: space :
+ - - - - - - - - + <--- 0xbfff1224
: extra space :
+-----------------+ <--- 0xbfff1220
The point of this is that there are some "SIMD" (Single Instruction, Multiple Data) instructions (also known in x86-land as "SSE" for "Streaming SIMD Extensions") which can perform parallel operations on multiple words in memory, but require those multiple words to be a block starting at an address which is a multiple of 16 bytes.
In general, the compiler can't assume that particular offsets from %esp
will result in a suitable address (because the state of %esp
on entry to the function depends on the calling code). But, by deliberately aligning the stack pointer in this way, the compiler knows that adding any multiple of 16 bytes to the stack pointer will result in a 16-byte aligned address, which is safe for use with these SIMD instructions.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…