zoukankan      html  css  js  c++  java
  • 2019-2020-1 20199303<Linux内核原理与分析>第二周作业

    2019-2020-1 20199303<Linux内核原理与分析>第二周作业

    1.汇编与寄存器的学习

    寄存器是中央处理器内的组成部份。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和位址。在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC)。在中央处理器的算术及逻辑部件中,包含的寄存器有累加器(ACC)。

      寄存器是内存阶层中的最顶端,也是系统获得操作资料的最快速途径。寄存器通常都是以他们可以保存的位元数量来估量,寄存器通常都用来意指由一个指令之输出或输入可以直接索引到的暂存器群组。寄存器是CPU内部的元件,寄存器拥有非常高的读写速度,所以在寄存器之间的数据传送非常快。
    寄存器用途:

      1.可将寄存器内的数据执行算术及逻辑运算;

      2.存于寄存器内的地址可用来指向内存的某个位置,即寻址;

      3.可以用来读写数据到电脑的周边设备。

    操作寄存器的寻址方式有七种
    立即寻址方式(Immediate addressing)

    寄存器寻址方式(Register addressing)

    直接寻址方式(Direct addressing)

    寄存器间接寻址方式(Register indirect addressing)

    寄存器相对寻址方式(Register relative addressing)

    基址变址寻址方式(Based indexed addressing)

    相对基址变址寻址方式(Relative based indexed addressing)

    2.实验过程

    首先熟悉一下vim操作

    然后测试的代码

    int g(int x)
    {
    return x+5;
    }
    
    int f(int x)
    {
    return g(x);
    }
    
    int main(void){
    return f(8)+1;
    }  
    

    输入gcc -S -o main.s main.c -m32得到main.s的汇编文件,可以用vi main.s打开得到的汇编代码与实验楼得到的代码有所区别。

    1.file   "main.c"
    2         .text
    3         .globl  g
    4         .type   g, @function
        5 g:
        6 .LFB0:
        7         .cfi_startproc
        8         pushl   %ebp
        9         .cfi_def_cfa_offset 8
    10         .cfi_offset 5, -8
    11         movl    %esp, %ebp
    12         .cfi_def_cfa_register 5
    13         movl    8(%ebp), %eax
    14         addl    $5, %eax
    15         popl    %ebp
    16         .cfi_restore 5
    17         .cfi_def_cfa 4, 4
    18         ret
    19         .cfi_endproc
    20 .LFE0:
    21         .size   g, .-g
    22         .globl  f
    23         .type   f, @function
    24 f:
    25 .LFB1:
    26         .cfi_startproc
    27         pushl   %ebp
    28         .cfi_def_cfa_offset 8
    29         .cfi_offset 5, -8
    30         movl    %esp, %ebp
    31         .cfi_def_cfa_register 5
    32         pushl   8(%ebp)
    33         call    g
    34         addl    $4, %esp
    35         leave
    36         .cfi_restore 5
    37         .cfi_def_cfa 4, 4
    38         ret
    39         .cfi_endproc
    40 .LFE1:
    41         .size   f, .-f
    42         .globl  main
    43         .type   main, @function
    44 main:
    45 .LFB2:
    

    然后输入g^.s*/d发现指令不能用,便手动dd删除之得到

    1 g:
    2         pushl   %ebp
    3         movl    %esp, %ebp
    4         movl    8(%ebp), %eax
    5         addl    $5, %eax
    6         popl    %ebp
    7         ret
    8 f:
    9          pushl   %ebp
    10         movl    %esp, %ebp
    11         pushl   8(%ebp)
    12         call    g
    13         addl    $4, %esp
    14         leave
    15         ret
    16 main:
    17         pushl   %ebp
    18         movl    %esp, %ebp
    19         pushl   $8
    20         call    f
    21         addl    $4, %esp
    22         addl    $1, %eax
    23         leave
    24         ret  
    

    刚开始对于一下片段在各函数头出现感到困惑

            pushl   %ebp
            movl    %esp, %ebp
    

    在查阅资料后了解到在函数调用过程中,ebp和esp之间的空间被称为本次函数调用的“栈帧”。函数调用结束后,处于栈帧之前的所有内容都是本次函数调用过程中分配的临时变量,都需要被“返还”。这样在概念上,给了函数调用一个更明显的分界。下图是一个程序运行的某一时刻的栈帧图:

    另一个问题就是对于所谓的堆栈空间,esp,和ebp作为栈顶和栈底都可以变化,这点与数据结构中严格的堆栈定义有所区别,更有点像队列的,但是因为其作为寄存器保存到是对应内存的地址其实也是合理的。

    2.代码对应的汇编执行的过程

    函数是从main开始执行的,所以17.18
    行建立主函数的堆栈空间,19行将立即数8压入内存中的堆栈空间作为f函数,此时修改了EIP寄存器,指令跳转到第8行f函数处。f函数前两行功能同主函数,第十一行将ebp中保存的堆栈底号加8压入堆栈空间,同时esp下移,此时栈顶指针对应内存空间保存的参数8在下一行call g中被g函数调用。然后g函数在四五行中将计算结果存入eax寄存器中被返回22行,将计算结果加1重新存入eax寄存器中。

  • 相关阅读:
    使用 ServiceStack 构建跨平台 Web 服务
    .NET的微型Web框架 Nancy
    orcale复制表结构及其数据
    利用PL/SQL Developer工具导出数据到excel,导入excel数据到表
    PLSQL导入/导出数据方法
    基于Quqrtz.NET 做的任务调度管理工具
    Web监听器导图详解(转)
    GIT分支管理是一门艺术(转)
    我需要完全理解这部分代码才能确保它能够正常工作,如果由我来修复代码中的问题,我是不会这么写的,因此希望你也不要这么来写(转)
    不要学习代码,要学会思考(转)
  • 原文地址:https://www.cnblogs.com/besti-20199303/p/11569034.html
Copyright © 2011-2022 走看看