stack of gcc

来源:互联网 发布:长虹55寸网络智能电视 编辑:程序博客网 时间:2024/06/05 13:23

栈是向下生长的,%esp记录着栈顶,%ebp记录着当前的栈禎

# 以下是主调函数
_start:
   push $3                # 函数参数
   push $2               # 函数参数
   call func               # 调用函数
   addl $8, %esp      # 删除参数占用的堆栈空间

# 参数入栈后,执行call指令,call指令做两件事:
#    1.将当前call指令的下一条指令的地址入栈
#    2.修改%eip = function_addr,i.e. 让%eip等于被调函数的入口地址

.func:
   pushl %ebp              # 将_start中的%ebp栈禎入栈   create stack frame
   movl  %esp, %ebp   # 将.func的栈禎保存到 ebp中
                                  # i.e. %ebp 保存的永远是当前函数的栈禎

|->subl  $8,   %esp   # 为local variable 申请两个局部变量空间,可能程序中使用两次pushl
|
|  .....
|      | 12(%ebp)  | 就是第二个参数
|      |  8(%ebp)  | 就是第一个参数
|      |  4(%ebp)  | 是调用.func的_start函数中的addl $8, %esp的地址,i.e. 函数返回地址 
|      |  %ebp     |  是调用func之前的ebp
|      |  -4(%ebp) | 第一个局部变量
|      |  -8(%ebp) | 第二个局部变量 %esp
|   .....
|
|->addl  $8,   %esp    # 释放两个局部变量占用的栈内存,与前面的subl $8, %esp对应

   movl ..., %eax        # 设置返回值
   movl %ebp, %esp  # 将%esp设置为%ebp,这样下一步popl时
                                # 能把调用func前的%ebp弹出来
   popl  %ebp            # 将%ebp恢复为调用func 前的%ebp
                                #  destory stack frame

   ret                        # ret指令与call指令是对应的
                               # ret 指令相当于popl %eip指令,经过popl后,
                               # %esp指向的是调用.func的_start函数中的
                               # addl 8, %esp的地址

注意观察:.func开头的两行  与 .func 的倒数2、3行是对应的

 

as     -o x.o   --gstabs+    x.s

ld      -o x                           x.o

原创粉丝点击