zoukankan      html  css  js  c++  java
  • 程序的机器级表示内容补充及扩展

    程序的机器级表示内容补充及扩展

    第五周练习补充

    • 代码

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

    • 每条指令相应栈帧的情况

    EIP & EBP & ESP

    eax, ebx, ecx, edx, esi, edi, ebp, esp等都是X86 汇编语言中CPU上的通用寄存器的名称,是32位的寄存器。如果用C语言来解释,可以把这些寄存器当作变量看待。

    比方说:add eax,-2 //可以认为是给变量eax加上-2这样的一个值。

    这些32位寄存器有多种用途,但每一个都有“专长”,有各自的特别之处。

    • EAX 是"累加器", 它是很多加法乘法指令的缺省寄存器。

    • EBX 是"基地址"寄存器, 在内存寻址时存放基地址。

    • ECX 是计数器, 是重复前缀指令和LOOP指令的内定计数器。(在汇编指令中,loop通常实现循环功能)

    • EDX 是被用来放整数除法产生的余数。

    • ESI/EDI分别叫做"源/目标索引寄存器",因为在很多字符串操作指令中, DS:ESI指向源串,而ES:EDI指向目标串.

    • EBP是"基址指针", 它最经常被用作高级语言函数调用的"框架指针". 在破解的时候,经常可以看见一个标准的函数起始代码:

        push ebp ;      保存当前ebp
        mov ebp,esp ;   EBP设为当前堆栈指针
        sub esp, xxx ;  预留xxx字节给函数临时变量.
        ...
      

    这样一来,EBP 构成了该函数的一个框架, 在EBP上方分别是原来的EBP, 返回地址和参数;EBP下方则是临时变量。函数返回时作mov %ebp , %esppop %ebp(相当于leave)、ret 即可。

    • ESP 专门用作堆栈指针,被形象地称为栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,ESP也就越来越小。(在32位平台上,ESP每次减少4字节)
    • esp:寄存器存放当前线程的栈顶指针
    • ebp:寄存器存放当前线程的栈底指针
    • eip:寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,然后继续执行。

    EIP,EBP,ESP都是系统的寄存器,里面存的都是些地址。

    栈的数据结构,主要有以下特点:后进先出。

    其实它还有以下两个作用:

    1. 栈是用来存储临时变量,函数传递的中间结果。
    2. 操作系统维护的,对于程序员是透明的。

    栈的原理

    • 写个小程序:

    当程序进行函数调用的时候,我们经常说的是先将函数压栈,当函数调用结束后,再出栈。这一切的工作都是系统帮我们自动完成的。但在完成的过程中,系统会用到下面三种寄存器:

     1.EIP
     2.EBP
     3.ESP
    
    • 当调用test函数开始时,三者的作用:

    1.EIP寄存器里存储的是CPU下次要执行的指令的地址。
    也就是调用完test函数后,让CPU知道应该执行main函数中的printf("End of function call")语句了。

    2.EBP寄存器里存储的是栈的栈底指针,通常叫栈基址,这个是一开始进行test()函数调用之前,由ESP传递给EBP的。(在函数调用前可以这么理解:ESP存储的是栈顶地址,也是栈底地址。)

    3.ESP寄存器里存储的是在调用函数test()之后,栈的栈顶。并且始终指向栈顶。

    • 当调用test函数结束后,三者的作用:

    1.系统根据EIP寄存器里存储的地址,CPU就能够知道函数调用完,下一步应该做什么,也就是应该执行main函数中的printf("End of function call")

    2.EBP寄存器存储的是栈底地址,而这个地址是由ESP在函数调用前传递给EBP的。等到调用结束,EBP会把其地址再次传回给ESP。所以ESP又一次指向了函数调用结束后,栈顶的地址。

    代码调试中的问题

    在把test.c编译成汇编代码时,我本来想用实验楼练习中的方法gcc –S –o test.s test.c -m32编译成32位的,可是遇到了比上次还不理解的问题。在上次练习时,代码开头有#include <stdio.h>时编译就会出错,而没有时就可以编译。

    但是这次代码开头有#include <stdio.h>时编译也会出错,而没有时还是不行,这个地方不知道怎么解决。

    所以我只好直接用gcc -S test.c 编译成汇编代码。

    当我习惯性的删除所有以"."开头的语句时,发现代码中出现了".LC0"和".LC1",我想起来这两个东西是我刚才删掉的以"."开头的语句中的东西,应该是调用了这两部分的函数,但是这两部分函数具体的结构表示不知道怎么看。

    本周代码托管截图

    其他(感悟、思考等,可选)

    这篇博客没有写本周的内容,只是对上周的内容的补充和扩展,以及更深入的理解。本周的内容会写在周天的博客中。

    其他内容

    因为在创建test.c 及test.s文件时放错了文件夹目录,所以复习了文件移动的指令。

    mv命令

    • 格式
      mv [options] 源文件或目录 目标文件或目录

    • [options]主要参数

    -i:交互方式操作。如果mv操作将导致对已存在的目标文件的覆盖,此时系统询问是否重写,要求用户回答”y”或”n”,这样可以避免误覆盖文件。

    -f:禁止交互操作。mv操作要覆盖某个已有的目标文件时不给任何指示,指定此参数后i参数将不再起作用。

    • 第二个参数

    当第二个参数类型是文件时,mv命令完成文件重命名,它将所给的源文件或目录重命名为给定的目标文件名。
    当第二个参数是已存在的目录名称时,源文件或目录参数可以有多个,mv命令将各参数指定的源文件均移至目标目录中。在跨文件系统移动文件时,mv先拷贝,再将原有文件删除,而链至该文件的链接也将丢失。

    • 应用实例

    (1)将/home/20145333中的所有文件移到当前目录中:

    $ mv /home/20145333/* .
    

    (2)将文件test.c重命名为test01.c:

    $ mv test.c test01.c
    

    (3)把当前目录的一个子目录里的文件移动到另一个子目录里

    $ mv  子目录名/*  另一个目录
    

    (4)移动当前文件夹下的所有文件到上一级目录

    $ mv * ../
    

    ("*"可以换成任意文件)

    安装了"tree"

  • 相关阅读:
    css重点章节复习—布局-边框-边距-浮动 (部分)
    (重点章节复习以及代码调整笔记)选择器:伪类和伪元素选择器(部分)
    css015 定位网页上的元素
    css014 响应式web设计
    3.MFC基础(三)消息映射
    2.MFC基础(二)窗口创建
    1.MFC基础(一)程序流程
    27.windows线程
    26.windows进程
    25.windows内存管理
  • 原文地址:https://www.cnblogs.com/rx719523850/p/5982920.html
Copyright © 2011-2022 走看看