This question already has an answer here:

I'm not understating why the parameters to printf are passed this way. mov [esp+20h+var_1C], eax mov [esp+20h+Format], offset Format ; "%d"

Why esp is added with 20h then substracted with 20h and esp doest added to point to next stack location for local vars ?

why the compiler simply didnt generate code like this: move eax, var_4 push eax move eax, Format push eax call printf

Ill be happy i some of you can either explain how push is replaced with this custom mov.

here is the source in c:

#include <stdio.h>

int main(void)
    int a;
    int b = 5;

    printf("%d", b);

    return 0;

here is the disassembly:

; Attributes: bp-based frame

; int __cdecl main(int argc, const char **argv, const char **envp)
public _main
_main proc near

Format= dword ptr -20h
var_1C= dword ptr -1Ch
var_4= dword ptr -4
argc= dword ptr  8
argv= dword ptr  0Ch
envp= dword ptr  10h

push    ebp
mov     ebp, esp
and     esp, 0FFFFFFF0h
sub     esp, 20h
call    ___main
mov     [esp+20h+var_4], 5
mov     eax, [esp+20h+var_4]
mov     [esp+20h+var_1C], eax
mov     [esp+20h+Format], offset Format ; "%d"
call    _printf
mov     eax, 0
_main endp

marked as duplicate by Jason Geffner, peter ferrie, jvoisin, Guntram Blohm supports Monica, w s Oct 15 '15 at 11:26

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.


push eax is precisely identical to

sub esp, 4
mov [esp], eax

Rather than using a bunch of pushes, they adjusted the stack pointer to where it would have been if they had used push. Then, they store each datum where it would have been. The effect is the same, it's just fewer instructions.

  • You mean that this peace of code: mov [esp+20h+var_4], 5 mov eax, [esp+20h+var_4] mov [esp+20h+var_1C], eax mov [esp+20h+Format], offset Format ; "%d" replaces the pushes before function call ? – Igal Oct 15 '15 at 13:07
  • @igal yes, but you skipped the sub instruction that reserves stack for those movs to go into. – sqykly Oct 15 '15 at 14:39

This is a standard GCC-generated prelude of a function.

and     esp, 0FFFFFFF0h

aligns stack on 16-byte boundary, then

sub     esp, 20h

reserves all stack used inside the function (also aligned on 16-byte boundary, see https://en.wikipedia.org/wiki/Data_structure_alignment). Then all operations with current local stack variables, including arguments to called functions, are done as

mov     [esp+20h+XXX]

MSVC 2010 (and probably others) would do more pushes instead of this mov-ing

  • I understand, but why the pushes replaced with moves in newer version of the compilers ? – Igal Oct 15 '15 at 13:12
  • @Igal A wild guess - the changed it for x64 and reused the code for x86. Check "Stack Pointer based local variable access" in codemachine.com/article_x64deepdive.html – Vitaly Osipov Oct 19 '15 at 20:16

Why esp is added with 20h then substracted with 20h and esp doest added to point to next stack location for local vars ?

The mov [esp+20h+Format], offset Format instruction is only a modified view of the mov [esp], offset Format. The disassembler tries to visualize the local variables and the stack frame in this way. The +20h is the size of the stack frame and the Format keyword means the offset of the Format parameter (-20h). Since it is a parameter, which will be passed to a function, it is placed at the top of the stack. It would be the same, if the function allocated only 18h stack frame and pushed the parameter values to the stack.

why the compiler simply didnt generate code like this:

mov eax, var_4
push eax
mov eax, Format
push eax
call printf

Because the stack pointer should not be modified in this way and this form is only 1 instruction and not 2.


HIgh and midlevevel languages has bascically two different calling conentions (assuming datawidth i max_bits, much faster, but maybe lesss readable, signed values are indicated by, LSHB * 1 and son on.

The assmbly codes not corrrect. The correct code is mov ["I"ESP), determindes the sign. Sihn is entirely determined på software. EVen simple asseblers and compilers havea sign Array/CLT classl

  • I fail to understand your answer, and even if i could understand it, i wouldn't know how it has anything to do with the question. – Guntram Blohm supports Monica Oct 13 '15 at 14:06

Not the answer you're looking for? Browse other questions tagged or ask your own question.