x86-64栈帧中的“红色区域” red zone of stack frame on x86-64
前几天看System V AMD64 ABI标准的时候发现栈帧的顶部后面有一块“red zone”,在学cs:app3e/深入理解操作系统的时候并没有遇到这个,总结一下。
引用标准中的话:
The 128-byte area beyond the location pointed to by %rsp is considered to be reserved and shall not be modified by signal or interrupt handlers. Therefore, functions may use this area for temporary data that is not needed across function calls. In particular, leaf functions may use this area for their entire stack frame, rather than adjusting the stack pointer in the prologue and epilogue. This area is known as the red zone.
译:在%rsp指向的栈顶之后的128字节是被保留的——它不能被信号和终端处理程序使用。因此,函数可以在这个区域放一些临时的数据。特别地,叶子函数可能会将这128字节的区域作为它的整个栈帧,而不是像往常一样在进入函数和离开时靠移动栈指针获取栈帧和释放栈帧。这128字节被称作红色区域。
简单点说,这个红色区域(red zone)就是一个优化。因为这个区域不会被信号或者中断侵占,函数可以在不移动栈指针的情况下使用它存取一些临时数据——于是两个移动rsp的指令就被节省下来了。
然而,标准只说了不会被信号和终端处理程序侵占,red zone还是会被接下来的函数调用使用的,这也是为什么大多数情况下都是叶子函数(不会再调用别的函数)使用这种优化。下面我举一个例子:
/*test.c*/
long test2(long a, long b, long c) /* 叶子函数 */
{
return a*b + c;
}
long test1(long a, long b)
{
return test2(b, a, 3);
}
int main(int argc, char const *argv[])
{
return test1(1, 2);
}
编译汇编与反汇编:
frank@under:~/tmp$ gcc test.c && objdump -d a.out
得到test1和test2对应的指令:
00000000004004d6 <test2>:
4004d6: 55 push %rbp
4004d7: 48 89 e5 mov %rsp,%rbp
4004da: 48 89 7d f8 mov %rdi,-0x8(%rbp)
4004de: 48 89 75 f0 mov %rsi,-0x10(%rbp)
4004e2: 48 89 55 e8 mov %rdx,-0x18(%rbp)
4004e6: 48 8b 45 f8 mov -0x8(%rbp),%rax
4004ea: 48 0f af 45 f0 imul -0x10(%rbp),%rax
4004ef: 48 89 c2 mov %rax,%rdx
4004f2: 48 8b 45 e8 mov -0x18(%rbp),%rax
4004f6: 48 01 d0 add %rdx,%rax
4004f9: 5d pop %rbp
4004fa: c3 retq
00000000004004fb <test1>:
4004fb: 55 push %rbp
4004fc: 48 89 e5 mov %rsp,%rbp
4004ff: 48 83 ec 10 sub $0x10,%rsp
400503: 48 89 7d f8 mov %rdi,-0x8(%rbp)
400507: 48 89 75 f0 mov %rsi,-0x10(%rbp)
40050b: 48 8b 4d f8 mov -0x8(%rbp),%rcx
40050f: 48 8b 45 f0 mov -0x10(%rbp),%rax
400513: ba 03 00 00 00 mov $0x3,%edx
400518: 48 89 ce mov %rcx,%rsi
40051b: 48 89 c7 mov %rax,%rdi
40051e: e8 b3 ff ff ff callq 4004d6 <test2>
400523: c9 leaveq
400524: c3 retq
可以看到test1移动了栈顶指针来获取栈帧空间,即sub $xxx, %rsp + leaveq的组合。但是test2并没有移动栈顶指针,而是直接使用ebp/esp(此时它们两个相等,由于是叶子也不用考虑内存对齐的问题)存放要使用的数据。栈帧布局如下:

最后提一点,Windows x64 ABI中并没有“red zone”这个概念,栈顶指针rsp的低地址处被认为是“volatile”和“unsafe”的——操作系统、调试器、终端处理程序等等都可能侵占该区域。
参考:
x86-64栈帧中的“红色区域” red zone of stack frame on x86-64的更多相关文章
- X86-64寄存器和栈帧--牛掰降解汇编函数寄存器相关操作
X86-64寄存器和栈帧 概要 说到x86-64,总不免要说说AMD的牛逼,x86-64是x86系列中集大成者,继承了向后兼容的优良传统,最早由AMD公司提出,代号AMD64:正是由于能向后兼容,AM ...
- X86-64寄存器和栈帧
简介 通用寄存器可用于传送和暂存数据,也可参与算术逻辑运算,并保存运算结果.除此之外,它们还各自具有一些特殊功能.通用寄存器的长度取决于机器字长,汇编语言程序员必须熟悉每个寄存器的一般用途和特殊用途, ...
- JAVA栈帧
简介 Java栈是一块线程私有的内存空间.java堆和程序数据相关,java栈就是和线程执行密切相关的,线程的执行的基本行为是函数调用,每次函数调用的数据都是通过java栈来传递的. Java栈与数据 ...
- 深入理解java虚拟机(十) Java 虚拟机运行时栈帧结构
运行时栈帧结构 栈帧(Stack Frame) 是用于虚拟机执行时方法调用和方法执行时的数据结构,它是虚拟栈数据区的组成元素.每一个方法从调用到方法返回都对应着一个栈帧入栈出栈的过程. 每一个栈帧在编 ...
- Java虚拟机之栈帧
写在前面的话:Java虚拟机是一门学问,是众多Java大神们的杰作,由于我个人水平有限,精力有限,不能保证所有的东西都是正确的,这里内容都是经过深思熟虑的,部分引用原著的内容,讲的已经很好了,不在累述 ...
- Java-JVM 栈帧(Stack Frame)
一.概述 栈帧位置 JVM 执行 Java 程序时需要装载各种数据到内存中,不同的数据存放在不同的内存区中(逻辑上),这些数据内存区称作运行时数据区(Run-Time Data Areas). 其中 ...
- java 栈和栈帧
文章转载自:http://www.tuicool.com/articles/URZrMnb jvm为每个新创建的线程都分配一个堆栈.堆栈以帧为单位保存线程的状态.jvm对堆栈只进行两种操作:以帧为单位 ...
- C函数调用过程原理及函数栈帧分析(转)
在x86的计算机系统中,内存空间中的栈主要用于保存函数的参数,返回值,返回地址,本地变量等.一切的函数调用都要将不同的数据.地址压入或者弹出栈.因此,为了更好地理解函数的调用,我们需要先来看看栈是怎么 ...
- Linux内核调试方法总结之栈帧
栈帧 栈帧和指针可以说是C语言的精髓.栈帧是一种特殊的数据结构,在C语言函数调用时,栈帧用来保存当前函数的父一级函数的栈底指针,当前函数的局部变量以及被调用函数返回后下一条汇编指令的地址.如下图所示: ...
随机推荐
- 传统编程和IoC的对比
ref:http://www.importnew.com/13619.html 传统编程:决定使用哪个具体的实现类的控制权在调用类本身,在编译阶段就确定了. IoC模式:调用类只依赖接口,而不依赖具体 ...
- NSTimer、CADisplayLink 内存泄漏
NSTimer.CADisplayLink 内存泄漏 内存泄漏的原因 CADisplayLink 要用 Taget 和 Selector 初始化,NSTimer 也可以用类似的方法初始化.这样初始化之 ...
- String类的构造方法(2)
写了常见的几个而已. 1:new 一个String类的时候系统会自动传一个空构造 public String(); 注意: 当对象初始化是 null时 和 对象是 "" 时,两者是 ...
- angular directive知识
一般来讲 directive名字遵循一下规则: 1.忽略以x-和data-为元素/属性的前缀 2.转化“:”,“-”,“_”命名为驼峰命名 如下所示 <div ng-controller=&qu ...
- js转换字符串为数值的方法
在js读取文本框或者其他表单数据的时候获得的值是字符串类型的,比如两个文本框a和b,假设获得a的value值为11,b的value值为9 ,那么a.value要小于b.value,由于他们都是字符串形 ...
- win32多线程编程
关于多线程多进程的学习,有没有好的书籍我接触的书里头关于多线程多进程部分,一是<操作系统原理>里面讲的相关概念 一个是<linux基础教程>里面讲的很简单的多线程多进程编程 ...
- Bmob云IM实现头像更换并存入Bmob云数据库中(1.拍照替换,2.相册选择)
看图效果如下: 1.个人资料界面 2.点击头像弹出对话框 3.点击拍照 4.切割图片,选择合适的部分 5.点击保存,头像替换完毕,下面看从相册中选择图片. 6.点击相册 7.任选一张图片 8.切割图片 ...
- 自适应 Tab 宽度可以滑动文字逐渐变色的 TabLayout(仿今日头条顶部导航)
TabLayout相信大家都用过,2015年Google大会上发布了新的Android Support Design库里面包含了很多新的控件,其中就包含TabLayout,它可以配合ViewPager ...
- 在X64系统中PowerDesigner无法连接MySQL的解决方法
在MySQL的官网http://dev.mysql.com/downloads/connector/odbc/下载,下个X64版本的,顺带也下了个X86的. 下载完成安装一切顺利(因为是X64系统,自 ...
- JVM性能调优,GC
刚刚做完了一个项目的性能测试,“有幸”也遇到了内存泄露的案例,所以在此和大家分享一下. 主要从以下几部分来说明,关于内存和内存泄露.溢出的概念,区分内存泄露和内存溢出:内存的区域划分,了解GC回收机制 ...