1>在linux下如果可执行文件依赖于其他共享库,那么系统就会从0x40000000开始分配到相应的空间,并将共享库装入到相应的空间
2>在i386中esp始终指向栈顶,而ebp固定指向函数活动记录的一个固定位置,Ebp所指向的数据是调用该函数前ebp中的值,这样可以保证安全返回。Ebp又叫帧指针
3>在i386中函数的调用方式:把所有或者一部分要传递的参数压入栈中,也可以直接使用寄存器,然后将当前指令的下一条指令压入栈中,跳到函数体执行。
4>i386函数函数体标准开头:
Push ebp :(压入old ebp)
Move ebp,esp :ebp=esp
Sub exp,xxx: 在栈上分配xxx字节临时空间
Push xxx :保存xxx寄存器现场;
标准结尾:
Pop xxx :恢复xxx寄存器现场;
Mov esp,ebp esp=ebp; 恢复esp 同时回收局部变量空间,注意这是通过帧指针得到的栈帧
Pop ebp : 恢复保存的ebp的值
Ret : 从栈中取得返回地址,并且跳转到该位置;
5>gcc有个-fomit-frame-pointer可以取消帧指针,也就是ebp的运算,而是通过esp直接计算帧上变量的位置
无帧指针被调函数代码
08048354 <a>:
8048354: 83 ec 10 sub $0x10,%esp
8048357: c7 44 24 08 01 00 00 movl $0x1,0x8(%esp)
804835e: 00
804835f: 8b 44 24 08 mov 0x8(%esp),%eax
8048363: 89 44 24 0c mov %eax,0xc(%esp)
8048367: 83 c4 10 add $0x10,%esp
804836a: c3 ret
有帧指针
08048354 <a>:
8048354: 55 push %ebp
8048355: 89 e5 mov %esp,%ebp
8048357: 83 ec 10 sub $0x10,%esp
804835a: c7 45 f8 01 00 00 00 movl $0x1,0xfffffff8(%ebp)
8048361: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
8048364: 89 45 fc mov %eax,0xfffffffc(%ebp)
8048367: c9 leave
8048368: c3 ret
6>调用惯例(Calling Convention):函数参数的传递顺序和方式:栈有从左到右,有从右到左,有的支持寄存器传递参数。
7>当函数返回后,esp指向指向参数下放,由调用方调整esp指针。这些都由编译器的调用惯例决定。
8>lea eax,[eax+0x30] : eax=eax+0x30
9>关于堆的理解:程序像操作系统申请一块适当大小的堆空间,然后程序自己管理这块空间,而具体来讲,管理着堆空间分配往往是程序的运行库,运行库相当于是操作系统“批发”了一块较大的堆空间,然后给程序“零售”用, 当售完后或程序有大量内存需求时,再根据实际需求向操作系统“进货”。运行空利用堆的分配算法来处理。在Linux中一般"批发"用系统调用brk();
10>linux2.6里面共享库的装载位于0xbfxxxxxx
11>大结构函数返回