标题:main函数的在调用其他函数前栈帧的困惑
只看楼主
qq243625411
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2016-1-17
结帖率:0
已结贴  问题点数:20 回复次数:3 
main函数的在调用其他函数前栈帧的困惑
学习深入理解计算机系统有关汇编那章,产生疑惑...
int main() {
  int a[11] = {49,38,65,97,26,13,27,49,55,4,5};
  insertsort(a, 11);
}
反汇编代码如下:(call insertsort以后都省去了)
080484da <main>:
80484da:        8d 4c 24 04                  lea    0x4(%esp),%ecx
80484de:        83 e4 f0                     and    $0xfffffff0,%esp
80484e1:        ff 71 fc                     pushl  -0x4(%ecx)
80484e4:        55                           push   %ebp
80484e5:        89 e5                        mov    %esp,%ebp
80484e7:        51                           push   %ecx
80484e8:        83 ec 34                     sub    $0x34,%esp
80484eb:        65 a1 14 00 00 00            mov    %gs:0x14,%eax
80484f1:        89 45 f4                     mov    %eax,-0xc(%ebp)
80484f4:        31 c0                        xor    %eax,%eax
80484f6:        c7 45 c8 31 00 00 00         movl   $0x31,-0x38(%ebp)
80484fd:        c7 45 cc 26 00 00 00         movl   $0x26,-0x34(%ebp)
8048504:        c7 45 d0 41 00 00 00         movl   $0x41,-0x30(%ebp)
804850b:        c7 45 d4 61 00 00 00         movl   $0x61,-0x2c(%ebp)
8048512:        c7 45 d8 1a 00 00 00         movl   $0x1a,-0x28(%ebp)
8048519:        c7 45 dc 0d 00 00 00         movl   $0xd,-0x24(%ebp)
8048520:        c7 45 e0 1b 00 00 00         movl   $0x1b,-0x20(%ebp)
8048527:        c7 45 e4 31 00 00 00         movl   $0x31,-0x1c(%ebp)
804852e:        c7 45 e8 37 00 00 00         movl   $0x37,-0x18(%ebp)
8048535:        c7 45 ec 04 00 00 00         movl   $0x4,-0x14(%ebp)
804853c:        c7 45 f0 05 00 00 00         movl   $0x5,-0x10(%ebp)
8048543:        6a 0b                        push   $0xb
8048545:        8d 45 c8                     lea    -0x38(%ebp),%eax
8048548:        50                             push   %eax
8048549:        e8 ed fe ff ff               call   804843b <insertsort>

以下是我写的main栈帧,不知对不对。


问题1:保存的%ecx和金丝雀上面的是什么?
问题2:  这栈帧在调用函数前保证了16个字节对齐了么?
问题3:  与上述代码无关:
           call 804846b <BinarySearch>
           add $0xc,%esp   
           sub $0x8,%esp
           push %eax
           push $0x8048610
           call 8048330 <printf@plt>
           同样在main函数里调用两个函数,但调用printf前比前一个函数时栈帧多了4个字节,保证了对齐了么?
可能有点长,麻烦了
搜索更多相关主题的帖子: 计算机系统 
2016-01-17 22:53
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
得分:20 
各编译器对函数入口的处理不尽相同,但大致处理过程差不多:
1、保存原函数现场,ebp=esp,使用ebp作为变址寻址
2、根据函数内定义的变量数量,让esp-足够的变量空间,即在此的栈操作会在你定义的变量地址更低的位置。
3、以ebp为基址,对变量做初始化。
4、数组的顺序同地址顺序,即由低往高,显然你对数组的存储顺序理解反了。

至于栈对齐,这不是你考虑的问题,16位系统只要地址值是2的倍数、32位系统只要地址值是4的倍数就是对齐的,如果通过汇编强行输入非对齐的栈地址会引发int0错误处理(int0在除0时也会引发)

能编个毛线衣吗?
2016-01-18 11:02
qq243625411
Rank: 1
等 级:新手上路
帖 子:2
专家分:0
注 册:2016-1-17
得分:0 
回复 2楼 wmf2014
呃...可能我没说清楚吧,底部是栈顶,地址随着向上不断增大...
1.你说的过程我还是有点懂的。
2.我还是很不懂, pushl  -0x4(%ecx),将什么参数给压入了 ?
3.gcc坚持一个x86编程指导方针,也就是一个函数使用的所有栈空间必须是16字节的整数倍..--《深入理解计算机系统》
  我这c代码是用gcc编译的..或许你说的栈对齐的要求不是我说gcc的要求?

[此贴子已经被作者于2016-1-18 13:26编辑过]

2016-01-18 13:24
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
得分:0 
就我理解:“一个函数使用的所有栈空间必须是16字节的整数倍”应该是指栈的起始地址是16的整数倍,代码“and    $0xfffffff0,%esp”应该就是保证栈指针esp是16的整数倍的。
pushl -0x4(%ecx)
该指令的含义是取出寄存器ecx的值,减去4,将得到的值作为地址,在内存找到该地址对应的值,将其压入栈中。

能编个毛线衣吗?
2016-01-18 14:14



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-461171-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.070444 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved