云课堂 Linux内核分析 通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

时间:2020-12-22 00:52:05

陈呵+《Linux内核分析》 MOOC课程http://mooc.study.163.com/course/USTC-1000029000

实验截图如下


云课堂 Linux内核分析 通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

将.开头的汇编语句删去。。我是手动删的,删了好久,在网上找到一条命令,还未验证

$/g/\s*\./d

云课堂 Linux内核分析 通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的


分析:

g:
    pushl   %ebp            ;ebp=x-16, esp=x-28, %esp=x-16
    movl    %esp, %ebp      ;ebp=x-28, esp=x-28, %esp=ebp[x-16]
    ;初始化新栈

    movl    8(%ebp), %eax   ;eax=25
    ;获取参数

    addl    $4, %eax       ;eax=29
    ;函数内x+4的运算

    popl    %ebp            ;将栈底设置为上一个栈的栈底,恢复旧栈,此时ebp=x-16, esp=x-24, %esp=eip[f:7]
    ret                     ;ret指令如下
    ;popl %eip              ;将eip设置为上次中断的位置,恢复执行流,此时ebp=x-16, esp=x-20, %esp=25, eip=[f:7]
    ;整个过程实现了恢复中断的执行流的功能,栈状态恢复为call之前[f:5]的状态,eip指向了[f:7]
    ;完成了{函数返回}
    
f:
    pushl   %ebp            ;ebp=x-4, esp=x-16
    movl    %esp, %ebp      ;ebp=x-16, esp=x-16
    ;初始化新栈

    subl    $4, %esp        ;增加栈位,此时ebp=x-16, esp=x-20,用来保存参数
    movl    8(%ebp), %eax   ;将eax设置为(x-16+8)所在栈的值,即25
    movl    %eax, (%esp)    ;将eax放到栈顶位置,此时ebp=x-16, esp=x-20, %esp=25,完成参数的传递
    ;整个过程实现了从栈中取值并将值压栈的操作
    ;配合执行流跳转前将25压栈的操作实现了{函数调用及参数的传递}
    ;指令1,3又将此值压栈是为了调用g做准备

    call    g               ;ebp=x-16, esp=x-24, %esp=eip[f:7], eip={g}
    ;跳转到g

    ;从g返回                ;ebp=x-16, esp=x-20, %esp=25, eip=[f:7]
    leave
    ;movl   %ebp, %esp      ;将栈顶设置为栈底,销毁当前栈,此时ebp=x-16, esp=x-16, %esp=ebp[x-4]
    ;popl   %ebp            ;恢复旧栈,此时ebp=x-4, esp=x-12, %esp=eip[main:6]
    ret
    ;整个过程实现了函数返回的作用
    ;与[g:5-6]不同在于此函数中执行过压栈的操作,所以要先销毁当前栈才能恢复旧栈,
    ;[g:5-6]因为没有压栈操作所以可以直接使用popl,是不是不用向其它函数传递参数就不用压栈存参数?
    

main:
    pushl   %ebp            ;将ebp压栈,此时设ebp=x, 则esp=x-4, esp指向的栈空间存储的是ebp
    movl    %esp, %ebp      ;将ebp的值设置为esp,此时ebp=x-4, esp=x-4, 
    ;整个过程实现了将旧栈保存并初始化新栈

    subl    $4, %esp        ;将esp=x-8,栈顶下移,增加栈位,此时ebp=x-4, esp=x-8
    movl    $25, (%esp)    ;将立即数25放到栈顶位置,此时ebp=x-4, esp=x-8, %esp=25
    ;整个过程实现将立即数25压栈

    call    f               ;call指令如下
    ;push   %eip            ;将下一条将要执行的指令的地址压栈,此时ebp=x-4, esp=x-12, %esp=eip[main:6]
    ;movl   f, %eip         ;将eip设置为f标号所指向的指令地址,此时eip = {f}
    ;整个过程实现了执行流跳转的功能,下一条指令将会执行标号f:所在的指令,

    ;从f返回
    addl    $1, %eax        ;eax=30
    ;函数内f(x)+1

    leave                   ;恢复栈
    ret
    ;函数返回,这里返回到调用此程序的函数中去了