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

    第1章 计算机工作原理

    实验的具体过程如下:

    一、实验的C语言代码如图所示:


    二、将C语言代码转化为汇编语言代码如图所示:


    三、堆栈空间示意图如图所示:

      在这里,0~9代表堆栈空间的标号,压栈时标号加1,出栈时标号减1。右侧的数字表示内存地址,EBP和ESP寄存器都指向栈底,即指向一个4字节存储单元的下边缘2000的位置,表示2000~2003这4个字节,也就是标号为0的存储单元,以此类推,标号为1的存储单元为1996~1999这4个字节。
    

    四、对汇编代码执行过程进行分析:

    程序从从汇编代码第18行开始执行,也就是从“main”开始执行,执行过程如下:

    • 第18行:这条指令的作用实际上就是把ebp寄存器的值压栈,pushl指令的功能是先把ESP寄存器指向标号1的位置,即标号加1或地址减4,然后将EBP寄存器的值标号0(地址2000)放到堆栈标号1的位置。

    • 第19行:开始执行上一条指令时,EIP寄存器已经自动加1指向了第19行语句,将EBP寄存器也指向标号1的位置。第18行和第19行语句是建立main函数自己函数调用堆栈空间。

    • 第20行:开始执行上一条指令时,EIP寄存器已经自动加1指向了第20行语句,把ESP寄存器减4,实际上是ESP寄存器向下移动和一个标号,指向标号2的位置。

    • 第21行:开始执行上一条指令时,EIP寄存器已经自动加1指向了第21行语句,把立即数5放入ESP寄存器指向的标号2位置,也就是第20行代码预留出来的标号2位置。第20和21行语句实在为接下来调用f函数做准备,即压栈f函数所需的参数。

    • 第22行:开始执行上一条指令时,EIP寄存器已经自动加1指向了第22行语句:“call f”。第22行语句开始执时,EIP寄存器已经自动加1指向了下一条指令,即的第23行语句,实际上把EIP寄存器的值(行号为23的指令地址,用行号23表示)放到了栈空间标号3的位置。因为压栈前ESP寄存器的值是标号2,压栈时ESP寄存器先减4个字节,即指向下一个位置标号3,然后将EIP寄存器的行号23入栈到栈空间标号3的位置。接着将f函数的第一条指令的行号9放入EIP寄存器,这样EIP寄存器就指向了f函数。接着开始执行f函数。

    • 第9行和第10行的语句和上述第18行和第19行的语句相同,作用是初始化函数自己的函数调用堆栈空间。

    • 第11行:将ESP寄存器减4,即指向下一个位置栈空间标号为5,实际上就是为了入栈预留出一个存储单元的空间。

    • 第12行:这是一个变址寻址的语句:EBP寄存器的值加8,当前EBP寄存器指向标号4的位置,加8即再向上移动两个存储单元加两个标号的位置,实际所指向的位置就是堆栈空间中标号2的位置,标号2的位置存储的立即数是5,那么这条语句的作用就是把立即数5放到了EAX寄存器中。

    • 第13行:把EAX寄存器中存储的立即数5放到ESP寄存器现在所指的位置,即第11行语句预留出来的栈空间标号5的位置。

    • 第14行:与上文第22行的语句作用类似,将ESP寄存器指向堆栈空标号6的位置,把EIP寄存器的内容行号15放到堆栈空间标号6的位置,然后把EIP寄存器指向函数g的第一条指令。即第2行的位置。

    • 第2行第3行的语句是为函数g建立一个逻辑上独立的函数调用堆栈空间。

    • 第4行:是一个变址寻址语句。EBP寄存器加8,也就是在当前EBP寄存器指向的栈空间标号7的位置基础上向上移动两个存储单元指向标号5,然后把标号5的内容放到EAX寄存器中。实际上,这一步是将函数g的参数取出来。

    • 第5行:把立即数2加到EAX寄存器中,就是5+2,EAX寄存器为7。这时EBP和ESP寄存器都指向标号7,EAX寄存器为7,EIP寄存器为代码行号6,函数调用空间如图所示。EBP或ESP+栈空间的标号表示存储的是某个时刻EBP或ESP寄存器的值,EIP+代码行号表示存储的是某个时刻的EIP寄存器的值。

    • 第6行和第7行语句的作用是拆除g函数调用堆栈,并返回到调用函数g的位置。使EIP寄存器指向代码第15行的位置。

    • 第15行和第16行:leav指令用于撤销堆栈。使EIP指向第23行的位置。

    • 第23行:把EAX寄存器加立即数2,也就是7+2,此时EAX寄存器的值为9。

    • 第24行和25行:撤销main函数的堆栈,使栈空间回到main函数开始执行之初的状态。


    五、使用gdb调试C语言程序

    1. 启动gdb调试:

    2. 查看main函数信息:

        从图中可见call指令自动把返回地址0x4004fc压入栈中。
      
    3. 查看f函数信息:

         在栈上保存上层帧的帧指针0x4004fc,然后将新的栈帧赋给帧指针%rsp。在这里rsp相当于书上的esp,rbp相当于书上的ebp。call指令自动把返回地址0x4004ed压入栈中。
      
    4. 查看g函数信息:

        在栈上保存上层帧的帧指针0x4004ed,然后将新的栈帧赋给帧指针%rsp。
      

    遇到的问题

    一、gdb调试问题

    在用gdb调试该C语言程序时,使用run命令会出现如下的错误:

    这样的话就不能查看该程序执行时,每一步的栈信息。在尝试了设置断点等方法后也没有解决该问题。接下来我会继续查阅相关资料,来解决该问题。


  • 相关阅读:
    LeetCode(287)Find the Duplicate Number
    LeetCode(290) Word Pattern
    LeetCode(205)Isomorphic Strings
    LeetCode(201) Bitwise AND of Numbers Range
    LeetCode(200) Number of Islands
    LeetCode(220) Contains Duplicate III
    LeetCode(219) Contains Duplicate II
    命令行执行Qt程序
    LeetCode(228) Summary Ranges
    redis 的安装和使用记录
  • 原文地址:https://www.cnblogs.com/SunMaolin/p/11567078.html
Copyright © 2011-2022 走看看