x86 Subroutines

Mark Smotherman. Last updated September 2002.

(under construction)

Introduction

... Microsoft has defined multiple calling conventions: (1) C declaration (cdecl), (2) standard call (stdcall), (3) fastcall, and (4) thiscall

Dedicated registers

        esp - stack pointer
        ebp - base pointer (Intel name for frame pointer)

Subroutine instructions

        call
        ret

Special instructions for stack frame support

        enter
        leave

Parameter passing

...

Calling program structure

           ...
           pushl parm2
           pushl parm1
           call
           addl  $(size_of_memory_for_parameters),%esp
           ...

Subroutine structure

        subr:
           pushl %ebp
           movl  %esp,%ebp
           pushl %ecx
           ... push other registers to save ...
           subl  %(size_of_memory_for_local_variables),%esp

           ... body of subroutine ...

           movl  %ebp,%esp
           ... pop other registers to restore (reverse order) ...
           popl  %ecx
           popl  %ebp
           ret

Example assembly code generated by C compiler


        void main() {         main:
          void swap();          pushl %ebp         ! save old bp
          int a,b;              movl %esp,%ebp     ! set new bp as current sp
          a = 5; b = 44;        subl $8,%esp       ! sub for a and b
          swap(&a,&b);          movl $5,-4(%ebp)   ! initialize a
        }                       movl $44,-8(%ebp)  ! initialize b
                                leal -8(%ebp),%eax ! form addr of b
                                pushl %eax         ! push onto stack
                                leal -4(%ebp),%eax ! form addr of a
                                pushl %eax         ! push onto stack
                                call swap          ! call
                                addl $8,%esp       ! clean parms off stack
                                leave
                                ret

        void swap(x,y)        swap:
        int *x,*y;              pushl %ebp         ! save old bp
        {                       movl %esp,%ebp     ! set new bp as current sp
          int temp;             subl $4,%esp       ! sub for temp
          temp = *x;            movl 8(%ebp),%eax  ! move addr x into eax
          *x = *y;              movl (%eax),%edx   ! indirectly get value in a
          *y = temp;            movl %edx,-4(%ebp) ! store into temp
          return;               movl 8(%ebp),%eax  ! move addr x into eax
        }                       movl 12(%ebp),%edx ! move addr y into edx
                                movl (%edx),%ecx   ! indirectly get value in b
                                movl %ecx,(%eax)   ! store indirectly into a
                                movl 12(%ebp),%eax ! move addr y into eax
                                movl -4(%ebp),%edx ! move temp into edx
                                movl %edx,(%eax)   ! store indirectly into b
                                leave
                                ret

Other resources


[History of subroutines page] [Mark's homepage] [CPSC homepage] [Clemson Univ. homepage]

mark@cs.clemson.edu