1

If I pass an argument to a function, it should be translated in assembly language into push something. I coded the following in C:

#include <stdio.h>

int sum(int a, int b,int c)
{
    int total;
    total = a + b + c;
    printf ("I will return now");
    return(total);
}

int media(int a, int b,int c)
{
    int total;
    total = (a + b + c)/3;
    printf ("\nI will return now\n");
    return (total);
}

int main ()
{
    int num1,num2,num3;
    char keypress[1];

    num1 = 5;
    num2 = 10;
    num3 = 15;
    printf ("\nCalling sum function\n");
    sum(num1,num2,num3);
    printf ("\nWaiting a keypress to call media function\n");
    scanf ("%c",keypress);
    media(num1,num2,num3);
    printf ("\nWaiting a keypress to end\n");
    scanf ("%c",keypress);
    return(0);
}

I compiled it: gcc -S example.c. It generated an example.s file and my expectation was to saw some push instructions. Here is the produced assembly code:

    .file   "example.c"
    .section    .rodata
.LC0:
    .string "I will return now"
    .text
    .globl  sum
    .type   sum, @function
sum:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $32, %rsp
    movl    %edi, -20(%rbp)
    movl    %esi, -24(%rbp)
    movl    %edx, -28(%rbp)
    movl    -24(%rbp), %eax
    movl    -20(%rbp), %edx
    addl    %eax, %edx
    movl    -28(%rbp), %eax
    addl    %edx, %eax
    movl    %eax, -4(%rbp)
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf
    movl    -4(%rbp), %eax
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   sum, .-sum
    .section    .rodata
.LC1:
    .string "\nI will return now"
    .text
    .globl  media
    .type   media, @function
media:
.LFB1:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $32, %rsp
    movl    %edi, -20(%rbp)
    movl    %esi, -24(%rbp)
    movl    %edx, -28(%rbp)
    movl    -24(%rbp), %eax
    movl    -20(%rbp), %edx
    addl    %eax, %edx
    movl    -28(%rbp), %eax
    addl    %edx, %eax
    movl    %eax, -4(%rbp)
    movl    -4(%rbp), %ecx
    movl    $1431655766, %edx
    movl    %ecx, %eax
    imull   %edx
    movl    %ecx, %eax
    sarl    $31, %eax
    movl    %edx, %ecx
    subl    %eax, %ecx
    movl    %ecx, %eax
    movl    %eax, -4(%rbp)
    movl    $.LC1, %edi
    call    puts
    movl    -4(%rbp), %eax
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1:
    .size   media, .-media
    .section    .rodata
.LC2:
    .string "\nCalling sum function"
    .align 8
.LC3:
    .string "\nWaiting a keypress to call media function"
.LC4:
    .string "%c"
.LC5:
    .string "\nWaiting a keypress to end"
    .text
    .globl  main
    .type   main, @function
main:
.LFB2:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    movl    $5, -4(%rbp)
    movl    $10, -8(%rbp)
    movl    $15, -12(%rbp)
    movl    $.LC2, %edi
    call    puts
    movl    -12(%rbp), %edx
    movl    -8(%rbp), %ecx
    movl    -4(%rbp), %eax
    movl    %ecx, %esi
    movl    %eax, %edi
    call    sum
    movl    $.LC3, %edi
    call    puts
    leaq    -13(%rbp), %rax
    movq    %rax, %rsi
    movl    $.LC4, %edi
    movl    $0, %eax
    call    __isoc99_scanf
    movl    -12(%rbp), %edx
    movl    -8(%rbp), %ecx
    movl    -4(%rbp), %eax
    movl    %ecx, %esi
    movl    %eax, %edi
    call    media
    movl    $.LC5, %edi
    call    puts
    leaq    -13(%rbp), %rax
    movq    %rax, %rsi
    movl    $.LC4, %edi
    movl    $0, %eax
    call    __isoc99_scanf
    movl    $0, %eax
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE2:
    .size   main, .-main
    .ident  "GCC: (Debian 4.7.2-5) 4.7.2"
    .section    .note.GNU-stack,"",@progbits

Of course, I'm missing something because I just saw two pushq instructions.

My question is what am I missing?

  • Answers below are accurate. Don't forget thought that push is not always used when calling functions in 32 bits architecture. You'll probably see mov DWORD PTR [ESP+0x8], 0x24, mov DWORD PTR [ESP+0x4], 0xa and mov DWORD PTR [ESP], 0x5 more often. – Hackndo Sep 4 '15 at 6:26
6

if I pass an argument to an function it should be translated in assembly language into push something

That's true for some 32-bit calling conventions, but your program is a 64-bit program and thus follows the System V Application Binary Interface for AMD64.

From https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI:

The calling convention of the System V AMD64 ABI is followed on Solaris, Linux, FreeBSD, Mac OS X, and other UNIX-like or POSIX-compliant operating systems. The first six integer or pointer arguments are passed in registers RDI, RSI, RDX, RCX, R8, and R9, while XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6 and XMM7 are used for floating point arguments. For system calls, R10 is used instead of RCX.

1

If you want assembly code without the use of push instruction from a C code, there is always the C prototype #inline.

0

-I think you must read more about passing parameters using x86-64 and x32 modes.

-As @jason Geffner has said, injecting aguments via 32 bits is performed by stacking em up, while via 64 bits, is different, they are stored in regisers (notably rsi,rdi)

-This link illustrates more the mechanism of printf arguments introducing in 64 bit processors.

  • More samples about printf command usage in:

X86-64 processing

x32 and below

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