zoukankan      html  css  js  c++  java
  • 一个简单程序的汇编执行过程分析

    • 题目自拟,内容围绕计算机是如何工作的进行;
    • 博客中需要使用实验截图
    • 博客内容中需要仔细分析汇编代码的工作过程中堆栈的变化
    • 总结部分需要阐明自己对“计算机是如何工作的”理解。

    实验环境:ubuntu64位

    源代码:

    int g(int x){
        return x + 4;
    }
    int f(int x){
        return g(x);
    }
    int main(){
        return f(10) + 5;
    }

    编译命令:

    gcc -S -o anlysis_assemble.s anlysis_assemble.c -m32 //

    生成的汇编代码为:

    .file    "anlysis_assemble.c"
        .text
        .globl    g
        .type    g, @function
    g:
    .LFB0:
        .cfi_startproc
        pushl    %ebp
        .cfi_def_cfa_offset 8
        .cfi_offset 5, -8
        movl    %esp, %ebp
        .cfi_def_cfa_register 5
        movl    8(%ebp), %eax
        addl    $4, %eax
        popl    %ebp
        .cfi_restore 5
        .cfi_def_cfa 4, 4
        ret
        .cfi_endproc
    .LFE0:
        .size    g, .-g
        .globl    f
        .type    f, @function
    f:
    .LFB1:
        .cfi_startproc
        pushl    %ebp
        .cfi_def_cfa_offset 8
        .cfi_offset 5, -8
        movl    %esp, %ebp
        .cfi_def_cfa_register 5
        subl    $4, %esp
        movl    8(%ebp), %eax
        movl    %eax, (%esp)
        call    g
        leave
        .cfi_restore 5
        .cfi_def_cfa 4, 4
        ret
        .cfi_endproc
    .LFE1:
        .size    f, .-f
        .globl    main
        .type    main, @function
    main:
    .LFB2:
        .cfi_startproc
        pushl    %ebp
        .cfi_def_cfa_offset 8
        .cfi_offset 5, -8
        movl    %esp, %ebp
        .cfi_def_cfa_register 5
        subl    $4, %esp
        movl    $10, (%esp)
        call    f
        addl    $5, %eax
        leave
        .cfi_restore 5
        .cfi_def_cfa 4, 4
        ret
        .cfi_endproc
    .LFE2:
        .size    main, .-main
        .ident    "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
        .section    .note.GNU-stack,"",@progbits

    删除伪代码,最简化后的代码为:

    g:
        pushl   %ebp
        movl    %esp, %ebp
        movl    8(%ebp), %eax
        addl    $4, %eax
        popl    %ebp
        ret
    f:
        pushl    %ebp    
        movl    %esp, %ebp
        subl    $4, %esp
        movl    8(%ebp), %eax
        movl    %eax, (%esp)
        call    g
        leave
        ret
    main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $4, %esp
        movl    $10, (%esp)
        call    f
        addl    $5, %eax
        leave
        ret

     首先对push指令进行分析:

    pushl %eax 等价于以下两句:

    subl $4, %esp            # esp = esp - 4, 栈向下增长, 栈顶指针向下增长

    movl %eax, (%esp) # 将寄存器eax内容取出到esp指向的地址的内存,即栈顶位置

    分析pop指令:

    popl %eax 等价于以下两句:

    movl (%esp), %eax  # 将esp指向的栈顶处内存值赋值给eax 

    addl $4, %esp          # esp栈顶向上缩小

    可以用这两个指令替代push 或 pop

    分析call指令

    call 0x12345 等价与以下两句:

    pushl %eip

    movl $0x12345, %eip

    分析 ret 指令

    ret 等价与 popl %eip

    这里注意的是eip不能在写汇编代码时直接修改,只能间接修改

    分析几段汇编指令片段

    例子一

    pushl $8  # 假设当前栈为空,栈顶和栈底都指向相同地址,esp = esp - 4, %esp = 8

    movl %esp, %ebp #则ebp也指向esp的位置

    subl $4,%esp #esp向下移动一个位置

    movl $8, (%esp) # 将8赋值到栈顶位置

    例子二

    pushl $8

    movl %esp, $ebp

    pushl %esp  # 将当前位置放到栈中

    pushl $8

    addl $4, %esp

    popl %esp

    分析leave和enter指令,它们分别由两条指令组成

    enter: #进入函数调用堆栈

      pushl %ebp

      movl %esp, %ebp

    leave: #撤销函数调用堆栈

      movl %ebp, %esp

      popl %ebp

    函数调用堆栈是由逻辑上多个堆栈叠加起来的。

    ebp , esp是相对的栈底和栈顶,每个函数都有自己的栈顶和栈底

    函数的返回值默认使用eax寄存器返回给上一级函数

  • 相关阅读:
    【CF722E】Research Rover
    【CF1519E】Off by One
    【CF1519D】Maximum Sum of Products
    【CF702F】T-Shirts
    【CF1364E】X-OR
    RPA应用场景-自动轮询汇总报表
    RPA应用场景-财务报表统计整合
    RPA应用场景-公积金贷款业务数据整合和报送
    RPA应用场景-信用卡交易争议后续流程
    RPA应用场景-日终清算操作
  • 原文地址:https://www.cnblogs.com/jinee/p/4536945.html
Copyright © 2011-2022 走看看