2006-05-26 (1)C语言函数的堆栈细述

原创 2006年05月26日 12:25:00

#include <stdio.h>
void swap(int *a,int *b)
{
        *a=*a^*b;
        *b=*a^*b;
        *a=*a^*b;
}
int main(int argc,char **argv)
{
        int a=100;
        int b=1000;
        swap(&a,&b);
        printf("the num of sub is %d/n",a-b);
        return(a-b);
}

 

C语言函数的堆栈细述
1堆栈的增加方向是向着低地址方向的

2函数的返回地址是在调用函数里开辟的

3可以这样来表示调用函数时栈桢的变化的esp(栈的顶部的指针)-->ebp(栈的底部)(本操作发生在被调用函数中)

4地址变量也会给开辟空间
5返回值放入寄存器中

 

5

        .file   "asm.c"
        .version        "01.01"
gcc2_compiled.:
.text
        .align 4
.globl swap
        .type    swap,@function
swap:
        pushl   %ebp                                                     //保存栈桢的底部
        movl    %esp, %ebp                                         //更新栈桢的底部,移动到新的栈桢
        movl    8(%ebp), %ecx                                     //取出&a---->ecx,edx//这两个寄存器在调用函数中就被保存起来                                                                                                                                       //了,不需要被调用函数的维护
        movl    8(%ebp), %edx                           
        movl    12(%ebp), %eax                                   //取出&b---->eax,,并取出b
        movl    (%eax), %eax             
        xorl    (%edx), %eax                                           //异或a,b,结果放到eax
        movl    %eax, (%ecx)                                         //保存到a   //下面有编译器生成的多余的指令
        movl    12(%ebp), %ecx                                    //取出&b---->ecx
        movl    8(%ebp), %edx                                      //取出&a---->edx
        movl    12(%ebp), %eax                                    //取出&b---->eax 并取出b
        movl    (%eax), %eax
        xorl    (%edx), %eax                                            //异或a,b,结果放到eax
        movl    %eax, (%ecx)
        movl    8(%ebp), %ecx
        movl    8(%ebp), %edx
        movl    12(%ebp), %eax
        movl    (%eax), %eax
        xorl    (%edx), %eax
        movl    %eax, (%ecx)
        popl    %ebp
        ret
.Lfe1:
        .size    swap,.Lfe1-swap
                .section        .rodata
.LC0:
        .string "the num of sub is %d/n"
.text
        .align 4
.globl main
        .type    main,@function
main:
        pushl   %ebp                                      //因为main本身就是一个函数、所以,跟swap时一样处理的
        movl    %esp, %ebp
        subl    $8, %esp                                //为整形a,b分配空间
        movl    $100, -4(%ebp)
        movl    $1000, -8(%ebp)
        subl    $8, %esp                                //为地址分配空间
        leal    -8(%ebp), %eax
        pushl   %eax                                      //作为参数调用压栈
        leal    -4(%ebp), %eax
        pushl   %eax
        call    swap
        addl    $16, %esp
        subl    $8, %esp
        movl    -8(%ebp), %edx
        movl    -4(%ebp), %eax
        subl    %edx, %eax
        pushl   %eax
        pushl   $.LC0
        call    printf
        addl    $16, %esp
        movl    -8(%ebp), %edx
        movl    -4(%ebp), %eax
        subl    %edx, %eax
        movl    %eax, %eax
        leave                                                     //movl %ebp,%esp             popl %ebp
        ret
.Lfe2:
        .size    main,.Lfe2-main
        .ident  "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-98)"
.Lfe1:
        .size    swap,.Lfe1-swap
                .section        .rodata
.LC0:
        .string "the num of sub is %d/n"
.text
        .align 4
.globl main
        .type    main,@function
main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp
        movl    $100, -4(%ebp)
        movl    $1000, -8(%ebp)
        subl    $8, %esp
        leal    -8(%ebp), %eax
        pushl   %eax
        leal    -4(%ebp), %eax
        pushl   %eax
        call    swap
        addl    $16, %esp
        subl    $8, %esp
        movl    -8(%ebp), %edx
        movl    -4(%ebp), %eax
        subl    %edx, %eax
        pushl   %eax
        pushl   $.LC0
        call    printf
        addl    $16, %esp
        movl    -8(%ebp), %edx
        movl    -4(%ebp), %eax
        subl    %edx, %eax
        movl    %eax, %eax
        leave
        ret
.Lfe2:
        .size    main,.Lfe2-main
        .ident  "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.1 2.96-98)"

 

C语言函数调用中堆栈知识

C语言的程序运行可以说就是不断的调用函数,从主入口的main函数到各种各样的库函数,再到用户自定义的完成特定功能的函数。 程序中关于一个函数的操作主要包括三个方面。①函数声明,②函数定义,③函数调用...
  • csu092000
  • csu092000
  • 2016年05月30日 21:09
  • 711

为何C语言(的函数调用)需要堆栈,而汇编语言却不需要堆

之前看了很多关于uboot的分析,其中就有说要为C语言的运行,准备好堆栈。 而自己在Uboot的start.S汇编代码中,关于系统初始化,也看到有堆栈指针初始化这个动作。但是,从来只是看到有人说...
  • u012581732
  • u012581732
  • 2013年12月25日 09:25
  • 948

C语言函数调用及栈帧结构

一、地址空间与物理内存 (1)地址空间与物理内存是两个完全不同的概念,真正的代码及数据都存在物理内存中。 物理储存器是指实际存在的具体储存器芯片,CPU在操纵物理储存器的时候都把他们当做内存来对待...
  • qq_29403077
  • qq_29403077
  • 2016年11月17日 19:10
  • 2419

C语言内存分配及堆栈问题总结

1. C语言程序编译的内存分配,堆与栈的区别  C语言程序编译的内存分配: 1.栈区(stack) --编译器自动分配释放,主要存放函数的参数值,局部变量值等; 2.堆区(he...
  • L_chxu
  • L_chxu
  • 2013年04月23日 20:41
  • 7022

C语言堆栈的区别

C语言中堆和栈的区别 一.前言: C语言程序经过编译连接后形成编译、连接后形成的二进制映像文件由栈,堆,数据段(由三部分部分组成:只读数据段,已经初始化读写数据段,未初始化数据段即BBS)和代...
  • zorelemn
  • zorelemn
  • 2016年09月17日 22:55
  • 2708

嵌入式系统C编程之堆栈回溯

前言      在嵌入式系统C语言开发调试过程中,常会遇到各类异常情况。一般可按需添加打印信息,以便观察程序执行流或变量值是否异常。然而,打印操作会占用CPU时间,而且代码中添加过多打印信息时会...
  • jxgz_leo
  • jxgz_leo
  • 2016年08月01日 17:26
  • 872

详解堆栈的几种实现方法——C语言版

基本的抽象数据类型(ADT)是编写C程序必要的过程,这类ADT有链表、堆栈、队列和树等,本文主要讲解下堆栈的几种实现方法以及他们的优缺点。   堆栈(stack)的显著特点是后进先出(Last-...
  • coding1994
  • coding1994
  • 2016年10月06日 21:40
  • 1989

C函数调用与堆栈的变化

原文地址:http://blog.chinaunix.net/uid-20718384-id-3418279.html 这篇blog试图讲明当一个c函数被调用时,一个栈帧(stack frame)是如...
  • Forward_Robin
  • Forward_Robin
  • 2015年07月26日 22:00
  • 603

C语言下程序的堆栈调用(详细,图示)

以前接触程序时,只知道程序写的对,一般都能运行出来,但是却不知道程序是怎么一步一步将每一步编译链接起来的,今天我们用汇编来看一下程序到底是怎么在程序中运行的。...
  • prokgtfy9n18
  • prokgtfy9n18
  • 2017年04月18日 19:10
  • 453

汇编程序调用c函数为什么需要设置栈?

保存现场/上下文,传递参数,保存临时变量。
  • thisway_diy
  • thisway_diy
  • 2017年07月31日 11:15
  • 396
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:2006-05-26 (1)C语言函数的堆栈细述
举报原因:
原因补充:

(最多只允许输入30个字)