在C / C ++中理解函数调用的堆栈框架?
我是C / C ++和汇编语言的新手。 这也可能是非常基本的问题。 我想了解如何构建堆栈帧以及按什么顺序将哪些变量(参数)推入堆栈? 一些搜索结果显示.... C / C ++的编译器根据在一个函数内执行的操作来决定。 例如,如果函数假设只是将传递的int param和return的值递增(类似于++运算符),它会将函数的所有参数和本地变量放入函数中的寄存器并执行加法。 ...想知道哪个寄存器用于返回/按值传递?....如何返回引用? .....差异b / w eax,ebx,ecx和edx。
请求书籍/博客/链接或任何类型的材料来理解寄存器,堆栈和堆引用在函数调用过程中使用/构建和销毁....以及主函数如何存储? 提前致谢
你的问题在这里是边界线。 程序员可能是一个更好的地方。
理解堆栈等概念的好书可能是Queinnec的Lisp In Small Pieces(它很好地解释了Lisp的一个堆栈)。 另外,SICP是一本很好的书。
D.Knuth的书和MMIX也是一个很好的阅读。
请仔细阅读Wikipedia调用堆栈页面。
理论上,不需要调用堆栈,并且某些语言和实现(例如旧的SML / NJ)没有使用任何堆栈(但在垃圾收集堆中分配了调用帧)。 请参阅A.Appel的旧论文垃圾收集可以比堆栈分配更快(并且了解有关垃圾收集的更多信息)。
通常C和C ++实现有一个堆栈(并且通常使用硬件堆栈)。 某些C局部变量可能没有任何堆栈位置(因为它们已经过优化或保存在寄存器中)。 有时,C局部变量的堆栈位置可能会发生变化(编译器会针对某些事件使用一个调用堆栈槽,而针对同一局部变量的其他事件使用另一个调用堆栈槽)。 当然,一些临时值可能会像局部变量一样被编译(所以留在寄存器中,在一个堆栈槽中,然后另一个堆栈中,等等)。 当优化编译器可以做变量的怪异技巧。
在IBM / 360或IBM z / series的一些旧机器上,没有硬件堆栈; C编译器使用的堆栈是软件约定(例如,某些寄存器专用于此用途,无需特定的硬件支持)
考虑一个递归定义函数的执行(或解释)(如旧的阶乘原始编码)。 阅读关于递归(通常在计算机科学中),原始递归函数,lambda演算,指称语义,堆栈自动机,寄存器分配,尾调用,continuation,ABI,中断,Posix信号,sigaltstack(2),getcontext(2), longjmp(3)等....等等...
另请阅读有关Computer Architecture的书籍。 在实践中,调用堆栈非常重要,以至于几个硬件资源(包括堆栈指针寄存器,通常是调用帧基址指针寄存器,以及可能隐藏的机器,例如与缓存相关的)在专用处理器上专用。
您还可以查看GCC编译器使用的中间表示。 然后使用-fdump-tree-all
或GCC MELT探针。 如果查看生成的程序集,请确保将-S -fverbose-asm
传递给gcc
命令。
另请参阅linux组件howto。
我给了很多链接。 回答好难,因为我不知道你的背景。
我想了解如何构建栈帧以及按什么顺序将哪些变量(参数)推入堆栈?
这取决于处理器的体系结构。 但是,通常,堆栈从高地址向低地址增长(如果我们将内存地址看作数值)。 一个堆栈帧是“无论这个函数放在堆栈上”
通常情况下,堆栈中的“东西”是:
C / C ++的编译器根据在一个函数内执行的操作来决定。 例如,如果函数假设只是将传递的int param的值递增1并返回(类似于++运算符),它会将函数和局部变量的参数放入寄存器中的函数内,并执行加法....想知道哪个寄存器用于返回/传递值?....如何返回引用?
编译器具有如何传递参数的规则,对于常规函数调用(即“内联”函数),参数总是以相同的顺序传递,寄存器和堆栈内存的组合相同。 如果情况并非如此,那么编译器在决定传递参数之前必须确切知道函数的作用。
不同的处理器架构有不同的规则。 x86-32通常有一个或两个寄存器用于输入参数,通常一个寄存器用于返回值。 x86-64最多使用5个寄存器将前五个值传递给函数。 任何进一步的参数都被传入寄存器。
返回引用与返回任何其他值没有区别。 值(在这种情况下是返回的对象的地址)。 在x86-32中,返回值在EAX中。 在x86-64中,返回值在RAX中。 在ARM中,R0用于返回值。 在29K中,R96用于返回值。
链接地址: http://www.djcxy.com/p/14773.html