movq%rbp,%rsp ; 使%rsp 和%rbp 指向同一位置,即子栈帧的起始处, 收回子栈帧空间 popq%rbp ; 将栈中保存的父栈帧的%rbp 的值赋值给%rbp,并且%rsp 上移一个位置指向父栈帧的结尾处 为了便于栈帧恢复,x86_64 架构中提供了 leave 指令来实现上述两条命令的功能。执行 leave 后,前面图中函数调用的栈帧...
在子函数调用时,执行的操作有:父函数将调用参数从后向前压栈 -> 将返回地址压栈保存 -> 跳转到子函数起始地址执行 -> 子函数将父函数栈帧起始地址(%rpb) 压栈 -> 将 %rbp 的值设置为当前 %rsp 的值,即将 %rbp 指向子函数栈帧的起始地址。 上述过程中,保存返回地址和跳转到子函数处执行由 call 一条...
如果是Caller Save 寄存器,在进行子函数调用之前,需要由调用者提前保存寄存器中的值(入栈),然后在子函数中可以向这些寄存器中写入任何数据;在完成调用后,恢复寄存器原来的值(出栈)。如果是Callee Save寄存器,父函数在进行子函数调用前不会保存寄存器中的值,在调用子函数后,子函数会首先保存寄存器中的值(入栈);子函...
函数运行阶段在调用栈上占用的这段空间就叫做栈帧,是编译原理运行时空间组织中活动记录(activation record)的一种实现 栈帧主要通过 ebp、esp 两个寄存器维护,ebp 始终指向栈底,esp 始终指向栈顶 每个函数被调用时执行下面两条命令 pushl %ebp; ebp入栈,保存调用者的栈帧基址,以便返回movl %esp, %ebp; 将当前 ...
shellcode就是我们注入到目标栈中的代码,shellcode的功能是使用execve函数得到一个shell。 x86-64的系统调用 从下图可见,x86_64架构取消了传统的中断形式的系统调用,使用syscall指令实现系统调用。并且存放参数的寄存器也有所变化。execve的系统调用号也从0xb变为了0x3b ...
这—地址上面(地址值递减方向)的空间便是这个函数将要使用的栈空间’它下面(地址值递增方向)是父函数使用的空间。 如此设置EBP寄存器后’便可以使用EBP寄存器加正偏移量来弓|用父函数的内容 使用EBP加负偏移量来引用本函数的局部变量° 比如ebp: 存放调用函数前ebp的值 ...
总结 x86架构与x64架构在函数于栈中调用过程的不同之处在于:x86架构下,函数的参数是直接存放到栈帧中的;而x64架构下,函数的参数是通过寄存器传参进入栈帧的。(当寄存器不够用,才会将参数直接存入栈帧)
在主函数栈帧如图所示,首先分配局部变量内存空间,然后保存主函数的堆栈帧,最后将2和3分别压入栈,接下来进入调用函数,如下图所示 然后开始调用函数,当执行call指令时会将返回地址压入栈以便执行栈帧上的ret指令时进行返回,将当前堆栈针移动到堆栈针,定义了堆栈帧的开始,从此刻开始进行函数调用内部,如下图 ...
当X86-64的函数需要的内存超过寄存器的内存时,就需要在函数栈上分配内存了; 一个函数在栈上分配的内存区域,叫做函数的栈帧; 运行时栈run-time stack 大部分函数的栈帧都是大小固定的; 有些函数的帧需要大小可变; 当前正在执行的函数的帧通常位于栈顶; 当函数P调用函数Q时,要将函数Q的返回地址压入函数P的栈...