补:第五周实验楼实践

实验楼实验

第一题

  • 使用VIM编写代码

  • 查看汇编文件

  • 删除gcc产生代码中以"."开头的编译器指令

分析过程

  1. main开始执行

     > pushl	%ebp    // 保存%ebp,设置新的帧指针
     > movl	%esp, %ebp
    

pushl $15//分配四字节的栈空间
call//调用f

  1. f初始换帧指针,分配栈空间
    > pushl %ebp // 初始换帧指针,分配栈空间
    > movl %esp, %ebp

pushl 8(%ebp)//将寄存器%esp中的8存入栈
call//调用g

  1. g初始换帧指针,分配栈空间

addl $3, %eax //执行1加上%eax
popl %ebp // 将g弹栈
ret // 返回f中call的位置

  1. b结束,同理ret返回main中call的位置

  2. main

addl $3, %eax //执行%eax加3的操作
leave // 返回准备栈 ,此时%ebp出栈
ret // 结束

总结一下这个过程的流程:

  • 这个程序的流程其实是f的过程调用了g的过程,f先把它的%ebp寄存器压入栈作为帧指针,然后压入被保存的寄存器、本地变量和临时变量,最上面是参数构造区域。然后再用call调用g,这时又把返回地址压入栈。

  • g被调用后,把它的帧指针%ebp压入栈,然后压入寄存器、本地变量、临时变量,最上面是参数构造区域。

  • g运算结束前,g会把%ebp弹出栈,然后ret指令弹出并跳转到之前call压入的地址,返回到f过程,最后因为leave,%ebp出栈。

下面展示用gdb单步跟踪各寄存器的值的变化

  • 在main函数设一个断点,使用disassemble获取汇编指令,再用info registers

  • call指令,此时%esp,%ebp和堆栈的值为:

  • 上一个函数基址入栈

  • 实参的计算

  • f函数汇编,实参入栈

  • call指令

  • leave指令先将%esp对其到%ebp,然后把栈顶弹给%ebp

  • 主函数汇编

指令 %esp %ebp 堆栈
push $0xf 0xbffff048 0xbffff048 0x0
call 0x80483e6 0xfffff044 0xfffff048 0xf 0x0
push %ebp 0xfffff040 0xfffff048 0x8048400 0xf 0x0
mov %esp,%ebp 0xbffff03c 0xfffff048 0xfffff048 0x8048400 0xf 0x0
mov 0x80483e7,%edx 0xfffff03c 0xfffff03c 0xfffff048 0x8048400 0xf 0x0
call 0x80483db 0xfffff034 0xfffff03c 0xf 0xfffff048 0x8048400 0xf 0x0
push %ebp 0xfffff030 0xfffff03c 0x80483f1 0xf 0xfffff048 0x8048400 0xf 0x0
mov %esp,%ebp 0xfffff030 0xfffff03c 0xfffff03c 0x80483f1 0xf 0xfffff048 0x8048400 0xf 0x0
mov 0x80483f2 %eax 0xfffff030 0xfffff030 0xfffff03c 0x80483f1 0xf 0xfffff048 0x8048400 0xf 0x0
ret 0xfffff030 0xfffff03c 0x80483f1 0xf 0xfffff048 0x8048400 0xf 0x0
leave 0xfffff03c 0xfffff03c 0xfffff048 0x8048400 0xf 0x0
ret 0xfffff040 0xfffff048 0x8048400 0xf 0x0
add $0x4,%esp 0xfffff044 0xfffff048 0xf 0x0
mov $0x3,%edx 0xfffff048 0xfffff48 0x0
ret 0xfffff04c 0x0

第二题:使用gdb的bt/frame/up/down指令动态查看调用线帧的情况


posted @ 2016-11-29 17:14  20145238荆玉茗  阅读(157)  评论(0编辑  收藏  举报