Disassemble such a simple program:

push ebp mov ebp, esp and esp, 0FFFFFFF0h sub esp, 10h mov eax, offset aHelloWorld ; "hello, world\n" 

The string and esp, 0FFFFFFF0h I always had eyesore, and its meaning is not explained in books on the reverse. They write that this is the alignment of the value in ESP along the 16-byte boundary, but the “alignment”, “zeroing of the first four bits” and “16 bytes” I do not add up to a complete idea. What's going on here? What is this for? Why is it necessary to reset 4 bits for alignment to 16 bytes?

Alignment, I understand as filling pieces of memory to the multiplicity of a number. For example, the aligned sections in PE are filled with zeros at the end, as shown by hiew.

Resetting the first four bits of ESP is like multiplying by 2^4 . But why is it not a pity for the compiler to squander so many addresses?

  • "Zeroing the first four bits of ESP is like multiplying by 2 ^ 4" - no, it's like resetting 4 bits. Ie, for example, if it was 0xFF (255), from after resetting 4 bits it will be 0xF0 (240). - insolor
  • I had in mind that after this reset, the value of ESP will be divided by 16, but it did not say so. - typemoon 4:04 pm
  • one
    Suppose we have the number 521 in the decimal number system, what needs to be done to bring it down to the number dividing by 100 is correct, turn 21 into 00 that would turn out 500. What is 10,000 in the binary number system? it is 16 decimal. thus, by analogy with what we just did in the decimal system, in order to make a binary number divisible by 16, you need to reset the lower 4 bits. Actually the lower 4 bits of the binary number is the remainder of the division by 16 - Mike

2 answers 2

Alignment by n is a change in the value so that it is a multiple of n .
Accordingly, there is an alignment of "down" and "up." For n equal to a power of two ( n = 2^k ), the alignments of the number x calculated as follows:

 x & ~(n - 1) // вниз, до ближайшего меньшего числа кратного n (x + n - 1) & ~(n - 1) // вверх, до ближайшего большего числа кратного n 

Unused pieces of memory are called padding and strictly speaking it has no relation to alignment. However, they can be filled with nothing ( dup alignment (?) ).

As the stack grows down, it is leveling from below, i.e. with help

 and esp, ~0xf 

    The stack grows towards decreasing addresses:

    Stack image

    That is, having received ESP and wishing to even it out, the lower 4 bits are cut off (at the same time, ESP will point to the memory location located after a certain number of bytes from the "past" ESP ). Then yes, "holes" can form in the stack. So it says in the documentation that ESP aligned on the 16-bit boundary. As for expediency, this is a question for developers, but they argue that this increases productivity.

    • I don’t think that sub esp, 10h refers in this code snippet to stack alignment on entry. Most likely, 16 bytes are reserved in the stack for the subsequent filling with arguments of a call to some function. - avp
    • Yes, I agree, I will correct it now - Alexey Sarovsky
    • Actually, the comment was just about the statement (wrong) (при этом ESP будет указывать, скорее всего, на уже занятое место), а потом вычитается 16 бит (чтобы попасть в еще не занятую область памяти) - avp