文档详情

第2讲编程基本概念(补充:C调用与堆栈)讲述.ppt

发布:2017-04-01约3.47千字共18页下载文档
文本预览下载声明
Agenda C语言函数调用堆栈框架 函数指针与回调函数 堆栈 堆栈是C语言程序运行时必须的一个记录调用路径和参数的空间 函数调用框架 传递参数 保存返回地址 提供局部变量空间 等等 C语言编译器对堆栈的使用有一套的规则 了解堆栈存在的目的和编译器对堆栈使用的规则是理解操作系统,特殊应用,代码注入等一些关键性代码的基础。 堆栈寄存器和堆栈操作 堆栈相关的寄存器 esp,堆栈指针(stack pointer) ebp,基址指针(base pointer) 堆栈操作 push 栈顶地址减少4个字节(32位) pop 栈顶地址增加4个字节 ebp在C语言中记录当前函数调用基址 esp ebp 高地址 低地址 esp 利用堆栈实现函数调用和返回 其他关键寄存器 cs : eip:总是指向下一条的指令地址 顺序执行:总是指向地址连续的下一条指令 跳转/分支:执行这样的指令的时候,cs : eip的值会根据程序需要被修改 call:将当前cs : eip的值压入栈顶,cs : eip指向被调用函数的入口地址 ret:从栈顶弹出原来保存在这里的cs : eip的值,放入cs : eip中 函数的堆栈框架 // 调用者 … call target … //建立被调用者target函数堆栈框架 pushl %ebp movl %esp, %ebp //拆除被调用者函数的堆栈框架 movl %ebp,%esp popl %ebp ret //被调用者target函数体 //do sth. … call指令: 1)将eip中下条指令地址A保存在栈顶 2)设置eip指向被调用程序代码开始处 将地址A恢复到eip中 函数堆栈框架的形成 call target 执行call之前 执行call时,cs : eip原来的值 指向call下一条指令,该值被 保存到栈顶,然后cs : eip的值 指向xxx的入口地址 进入target 第一条指令: pushl %ebp 第二条指令: movl %esp, %ebp 函数体中的常规操作,可能会压栈、出栈 退出target movl %ebp,%esp popl %ebp ret esp ebp 高地址 低地址 cs : eip esp ebp esp ebp esp C函数调用例子 源文件:test.c main函数调中用函数p1和p2 gcc –g 编译出可执行文件test objdump –S获得test反汇编文件 观察p2的堆栈框架 从test的反汇编文件中找到p2的反汇编代码 int p2(int x,int y) { push %ebp mov %esp,%ebp return x+y; mov 0xc(%ebp),%eax add 0x8(%ebp),%eax } movl %ebp,%esp pop %ebp ret 建立框架 拆除框架 ebp esp ebp 调用者 堆栈 框架 esp ebp y x 高地址 低地址 如何传递参数给p2的 … z=p2(x,y); pushl 0xfffffff8(%ebp) pushl 0xfffffff4(%ebp) call 804839b p2 add $0x8,%esp mov %eax,0xfffffffc(%ebp) printf(%d=%d+%d\n,z,x,y); pushl 0xfffffff8(%ebp) pushl 0xfffffff4(%ebp) pushl 0xfffffffc(%ebp) push $0x8048510 call 80482b0 printf@plt … p2的返回值是如何返回给main的? 调用者 堆栈 框架 esp ebp y的值 x的值 高地址 低地址 被调用者 堆栈 框架 ebp cs:eip esp ebp esp esp 观察main中的局部变量 ebp int main(void) { push %ebp mov %esp,%ebp sub $0x18,%esp … char c=a; movb $0x61,0xfffffff3(%ebp) int x,y,z; x=1; movl $0x1,0xfffffff4(%ebp) y=2; movl $0x2,0xfffffff8(%ebp) … 调用者 ebp esp ebp esp esp c=‘a’ x=1 y=2 高地址 低地址 观察程序运行时堆栈的变化 eip eip eip eip main … p1(c) … p2(x,y)
显示全部
相似文档