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语言函数调用时,栈帧用来保存当前函数的父一级函数的栈底指针,当前函数的局部变量以及被调用函数返回后下一条汇编指令的地址.如下图所示: ...
随机推荐
- JAVA_String、StringBuilder、StringBuffer区别
String.StringBuilder.StringBuffer均为字符串 类 需要注意的一些问题 String StringBuilder StringBuffer 一旦创建,不能对其内容进行更改 ...
- 9月24日noip模拟赛解题报告
1.校门外的树(tree.c/cpp/pas 128M,1s) Description LSGJ扩建了,于是校门外有了一条长为L的路.路上种了一排的树,每相邻两棵树之间的距离为1,我们可以把马路看成一 ...
- 看源码和写demo是一种比较容易提升的方式
github就是要这么用才行.看别人的源码,就能了解到很多规范,而写demo,就是自己写出自己的代码.莫欺少年穷
- 网站如何集成百度UEditor编辑器
在平时的网站维护使用过程中,富文本编辑器是网站必不可少的元素之一.现在市面上各种编辑器功能设计参差不齐,自己做了几个网站都是用蝉知建站系统做的,而蝉知默认内置的编辑器是KindEditor,功能简单, ...
- AFN默认请求和响应的处理
1.默认的响应的解析 1.1 AFN默认不支持接受text/html数据类型,只需要增加即可 manager.responseSerializer.acceptableCont ...
- JS -- Variables As Properties
Variables As Properties When you declare a global JavaScript variable, what you are actually doing i ...
- http://codeforces.com/contest/402/problem/E
E. Strictly Positive Matrix time limit per test 1 second memory limit per test 256 megabytes input s ...
- php追加编译GD库
一.准备工作. 安裝 GD 前需要安裝 jpegsrc.v7.tar.gz, libpng-1.6.17.tar.gz, zlib-1.2.8.tar.gz, freetype-2.5.5.tar.g ...
- SQLServer中SQL语句与可执行二进制语句
SQLServer可以执行正常SQL语句也可以执行被转换的二进制语句,一般会用此方法进行数据库注入操作,骗过基本的字符过滤 --将二进制格式转为普通SQL语句 ) = 0x53454C45435420 ...
- Hibernate Mapping Exception:-9
if("true".equals(map.get("isAudited"))){ isAudited="=";//已审核 }else{ is ...