免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5867 | 回复: 9
打印 上一主题 下一主题

[堆栈] 函数中,局部变量压栈,为什么堆栈指针不进行递减操作? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-03-29 14:03 |只看该作者 |倒序浏览
20可用积分
《汇编语言程序设计基础》  246--247页, 疑惑: 函数的局部变量被压入堆栈,为什么指针不变化呢?

还请大家指教,谢谢!
  

示意图大概如下:

function:

  pushl %ebp                            # 保护main中的ebp
  movl %esp, %ebp                   # 保护main中的esp
    ....


程序堆栈

-----------------------------------

------------------------------------
           函数参数 3                        16(%ebp)
------------------------------------
           函数参数 2                         12(%ebp)
------------------------------------
           函数参数 1                         8(%ebp)
------------------------------------
           返回地址                   4(%ebp)
------------------------------------
           旧的EBP值                  (%ebp)       <---------- ESP(堆栈指针)        #疑惑,下面局部变量也压入堆栈,当前堆栈指针为什么不指向局部变量位置呢?
------------------------------------
           局部变量 1                         -4(%ebp)
------------------------------------
           局部变量 2                         -8(%ebp)
-------------------------------------
           局部变量 3                          -12(%ebp)
-------------------------------------

最佳答案

查看完整内容

一个汇编函数的模型如下:pushl %ebp // 保存ebp值于栈上movl %esp, %ebp // 保存esp值于ebp寄存器/* same op */leave // 相当于:movl %ebp, %esp // popl %ebp // 此时esp指向了返回地址ret // 返回栈上申请变量时会移动esp指针,这时esp原值已被保存,可随意使用举个例子函数中定义一个 ...

论坛徽章:
0
2 [报告]
发表于 2010-03-29 14:03 |只看该作者
一个汇编函数的模型如下:

pushl %ebp              // 保存ebp值于栈上
movl  %esp, %ebp   // 保存esp值于ebp寄存器
/* same op */
leave                      // 相当于:movl %ebp, %esp
                              //             popl  %ebp
                              // 此时esp指向了返回地址
ret                         // 返回

栈上申请变量时会移动esp指针,这时esp原值已被保存,可随意使用
举个例子
函数中定义一个变量 int i = 5, 则

pushl %ebp
movl  %esp, %ebp
subl  $4, %esp            // 为i在栈上开辟空间
......
leave
ret

论坛徽章:
0
3 [报告]
发表于 2010-03-29 14:25 |只看该作者
当前ESP指向局部变量3的下方空余地方。假设栈向低端地址生长。

int f(int i, int j, int k)
{
int ii, jj, kk;
  ii = 11;
  kk = 33;
  printf("kk %p  k %p\n", &kk, &k);
}



f:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $40, %esp
        movl    $11, -8(%ebp)
        movl    $33, -12(%ebp)
        leal    16(%ebp), %eax
        movl    %eax, 8(%esp)
        leal    -12(%ebp), %eax
        movl    %eax, 4(%esp)
        movl    $.LC0, (%esp)
        call    printf
        leave
        ret

论坛徽章:
0
4 [报告]
发表于 2010-03-29 15:55 |只看该作者
当前ESP指向局部变量3的下方空余地方。假设栈向低端地址生长。

int f(int i, int j, int k)
{
int ii, ...
思一克 发表于 2010-03-29 14:25


非常感谢指点!

    也就是说 局部变量是 通过 mov 操作内存来 将操作数压入堆栈,而不是通过push把其地址压入堆栈中? 所以 堆栈指针没有指向堆栈顶端?

  就是借用 堆栈来代替register ,提高可操作空间?

  不知道是不是这样,还请指点!  

论坛徽章:
0
5 [报告]
发表于 2010-03-29 16:05 |只看该作者
一个汇编函数的模型如下:

pushl %ebp              // 保存ebp值于栈上
movl  %esp, %ebp   // 保存es ...
scaleray 发表于 2010-03-29 14:30



    非常感谢指点!

函数的stack指针和frame指针,以及返回时的出栈那里清楚

就是疑惑 “subl  $4, %esp            // 为i在栈上开辟空间 ”

为什么要人为的 递减 stack pointer  ?

看了楼上2位的回答,现在大概清楚了,不知道这么理解对不对?

    声明局部变量,只是预先申请一定空间,此时并不一定用到这块,也就是说这个时候并没有任何压栈的操作,
如果用的时候也只是把堆栈当作内存操作一样,通过以ebp为基址的变址寻址方式,来操作堆栈中的内存单元,
也就是mov操作,而并非push压栈操作

理解的不是太好,可能描述的不是很清楚,或是很繁琐罗嗦,还请见谅

论坛徽章:
0
6 [报告]
发表于 2010-03-29 16:12 |只看该作者
回复 5# nine8


    我有一个感觉,楼主可能受到上学时那种栈的概念的影响,一直把栈顶作为基准,只会push、pop,其实不管是堆也好栈也好,都是内存,都可以抽象成数组。

论坛徽章:
0
7 [报告]
发表于 2010-03-29 16:38 |只看该作者
回复  nine8


    我有一个感觉,楼主可能受到上学时那种栈的概念的影响,一直把栈顶作为基准,只会pu ...
doofy 发表于 2010-03-29 16:12



    恩,对对,呵呵,原来以为堆栈都是 push ,pop这么用的,然后堆栈指针相应的增加或递减

论坛徽章:
0
8 [报告]
发表于 2010-03-29 16:38 |只看该作者
回复 5# nine8


是的。
你对应C和汇编一看就知道了。
STACK FRAME 栈帧

论坛徽章:
0
9 [报告]
发表于 2010-03-29 16:42 |只看该作者
回复 8# 思一克


    恩,这回清楚了,呵呵

   非常感谢!

  版主你那么多分,这次的分就加给别人啦 ,但对楼上的朋友都是非常感谢的!

论坛徽章:
0
10 [报告]
发表于 2010-03-29 16:56 |只看该作者
回复  思一克


    恩,这回清楚了,呵呵

   非常感谢!

  版主你那么多分,这次的分就加给别人 ...
nine8 发表于 2010-03-29 16:42



好的。不需要加给我。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP