Linux下程序的机器级表示学习心得

上周学习完Linux程序的机器级表示后,对于其中有些还是掌握的不太透彻。对于老师提出的关于本章一些细节的问题还是有不会,所以又重新温习了一下上周的学习内容,以下为学习心得。

分析反汇编

操作过程

  • 分析反汇编采用了书上的一个简单案例。C语言代码如下。

      	int a(int x)
    {
    returnx+1;
    } int b(int x)
    {
    return a(x);
    } int main (void)
    {
    return b(8)+14;
    }
  • 使用vim编辑器编译代码main.c

  • 使用命令gcc -S main.c -o main.s得到汇编代码。(此时的汇编代码有以.开头的代码,删除它们之后就是正常书中给出的汇编代码。

  • 得到的汇编代码

  • 使用gdbbt/frame/up/down指令动态查看调用线帧的情况。



分析

  • main:开始执行,保存帧指针%ebp,并设置新的帧指针

  • pushl $8分配4字节的栈空间,并且设置arg1=8

  • 调用b:call b

  • b同样初始化帧指针,分配栈空间,和之前的main函数相同

  • pushl 8(%ebp)%esp中的立即数8存入栈中

  • 调用a:call a

  • a被调用,初始化栈指针,分配栈空间

  • %eax 与立即数 1 相加

  • 在a结束前弹栈

  • ret返回b中call的调用位置

  • b也结束,return返maincall调用的位置

  • main继续 %eax 加14的操作

  • leave为返回准备栈,相当于%ebp出栈,最后ret结束

即:调用者P和被调用者Q,则Q的参数放在P的栈帧中,当P调用Q的时候,P中的返回地址被压入栈中,形成P的栈帧末尾。返回地址就是当程序从Q返回时应继续执行的地方,Q栈帧从保存的帧指针的值开始后是保存其他寄存器的值。

结合backtrace命令分析栈帧

  • 首先backtrace/bt用来打印栈帧指针,也可以在该命令后加上要打印的栈帧的个数,查看程序执行到此时,是经过哪些函数呼叫的程序,程序“调用堆栈”是当前函数之前的所有已调用函数的列表(包括当前函数)。每个函数及其变量都分配了一个“帧”,最近调用的函数在0号帧中(“底部”帧)

  • 命令有

         - `fame farme1 `用于打印指定栈帧
    - ` info reg `查看寄存器使用情况
    - ` info stack` 产看堆栈使用情况
    - `up/down` 跳到上一层/下一层函数
  • 综述:

        - 先将调用者(A)的堆栈的基址(`%ebp`)入栈,以保存之前任务的信息。
    
        - 然后将调用者(A)的栈顶指针(`%esp`)的值赋给`%ebp`,作为新的基址(即被调用者B的栈底)。
    
        - 然后在这个基址(被调用者B的栈底)上开辟(一般用sub指令)相应的空间用作被调用者B的栈空间。
    
        - 函数B返回后,从当前栈帧的%ebp即恢复为调用者A的栈顶(`%esp)`,使栈顶恢复函数B被调用前的位置;然后调用者A再从恢复后的栈顶可弹出之前的%ebp值(可以这么做是因为这个值在函数调用前一步被压入堆栈)。这样,`%ebp`和`%esp`就都恢复了调用函数B前的位置,也就是栈恢复函数B调用前的状态。这样就解释了栈帧的出现和消失

    这个过程在AT&T汇编中通过两条指令完成,即:leaveret。这两条指令更直白点就相当于:mov %ebp , %esp pop %ebp

  • 下面我们使用GDB调试main.c的代码,使用刚才编译好的main镜像。

    - gdb start (启动gdb)

    - (gdb) file main (加载镜像文件)

    - (gdb) break main (把main()设置为断点,注意gdb并没有把断点设置在main的第一条指令,而是设置在了调整栈指针为局部变量保留空间之后)

    - (gdb) run (运行程序)

    - (gdb) stepi (单步执行,stepi命令执行之后显示出来的源代码行或者指令地址,注意:都是即将执行的指令,而不是刚刚执行完的指令!对于更复杂的例子会有明显的变化)



利用gdb对寄存器进行分析

通过gdb调试可执行文件查看%eip, %ebp, %esp 等寄存器内容如何变化。

  • 在linux中gdb调试汇编文件需要先用gcc -g3 -o * *.c的命令来将c语言文件编译成可调试汇编的可执行文件。

  • 通过调试过程中的stepiprint /x $***可以查询到相应寄存器的内容:

  • 根据之前的main函数逐步使用上面的代码,可以获得不同寄存器的变化。

| number | %eax寄存器变化| %esp寄存器变化|%ebp寄存器变化时间|

| -----------| :-----------:|:------------:|:---------------:|

| 1 | Ox4004fc | Oxffffde18 | Oxffffde20

| 2 | Ox4004fc | Oxffffde18 | Oxffffde20

| 3 | Ox8 | Oxffffde18 | Oxffffde20

| 4 | Ox8 | Oxffffde18 | Oxffffde20

| 5 | Ox8 | Oxffffde10 | Oxffffde20

| 6 | Ox8 | Oxffffde08 | Oxffffde20

| 7 | Ox8 | Oxffffde08 | Oxffffde08

| 8 | Ox8 | Oxffffde08 | Oxffffde08

| 9 | Ox8 | Oxffffde08 | Oxffffde08

| 10 | Ox9 | Oxffffde08 | Oxffffde08

| 11 | Ox9 | Oxffffde10 | Oxffffde20

| 12 | Ox9 | Oxffffde18 | Oxffffde20

| 13 | Ox9 | Oxffffde28 | Oxffffde30

| 14 | Ox9 | Oxffffde30 | Oxffffde30

| ... | ... | ... | ...

  • 如果想观察三个寄存器的每一步的变化配合gdb stepi可以重复上述步骤。

  • 部分过程截图。

  • 由上图可以看到三个寄存器的初始值

  • 由上图可以看到三个寄存器在执行完第一条指令之后的内容的变换

    注意:在64位中rip就是eiprbp就是ebprsp就是。

Linux下程序的机器级表示学习心得的更多相关文章

  1. CSAPP:第三章程序的机器级表示3

    程序的机器级表示3 关键点:过程.调试.指针 过程1.运行时栈2.转移控制3.数据传递4.栈上的局部存储5.寄存器中的局部存储空间理解指针使用GDB调试器 过程 1.运行时栈   x86-64的栈向低 ...

  2. CSAPP:第三章程序的机器级表示2

    CSAPP:程序的机器级表示2 关键点:算术.逻辑操作 算术逻辑操作1.加载有效地址2.一元二元操作3.移位操作 算术逻辑操作   如图列出了x86-64的一些整数和逻辑操作,大多数操作分成了指令类( ...

  3. CS:APP Chapter 3 程序的机器级表示-读书笔记

    3.1 程序的机器级表示 发展历史 Intel,AMD,ARM 等企业各有又是,CPU 从 8 位发展到 16 位,再到 32 位,近几年发展到 64 位,当下的 CPU 体系被称为 x86-64 体 ...

  4. Windows 7 下如何设置机器级别的DCOM权限

    Windows 7 下如何设置机器级别的DCOM权限 To grant Remote Activation permissions to the SMS Admins group From the S ...

  5. Linux下 两台机器文件/文件夹 相互拷贝

    Linux下 两台机器文件/文件夹 相互拷贝 设有两台机器 :A:*.101及 B:*.102. 把A下的.temp/var/a.txt拷贝到B机器的/text/目录下: 进入B机器:scp root ...

  6. CSAPP:第三章程序的机器级表示1

    CSAPP:程序的机器级表示1 关键点:数据格式.操作数指示符. 数据格式访问信息操作数指示符举例说明 数据格式   术语字(word)表示16位数据类型,32位数为双字(double words), ...

  7. 六星经典CSAPP-笔记(3)程序的机器级表示

    1.前言 IA32机器码以及汇编代码都与原始的C代码有很大不同,因为一些状态对于C程序员来说是隐藏的.例如包含下一条要执行代码的内存位置的程序指针(program counter or PC)以及8个 ...

  8. CSAPP 3 程序的机器级表示

    1 本章总述 1) 通过让编译器产生机器级程序的汇编表示, 学习了编译器及其优化能力, 以及机器.数据类型和指令集; 2) 学习了程序如何将数据存储在不同的内存区域中 -- 程序开发人员需要知道一个变 ...

  9. 深入理解计算机系统 第三章 程序的机器级表示 Part2 第二遍

    第一遍对应笔记链接 https://www.cnblogs.com/stone94/p/9943779.html 本章汇编代码中常出现的几个指令及其含义 1.push 操作数的个数:1 将操作数(一般 ...

随机推荐

  1. cross-compler toolchains--clfs

    http://www.cnblogs.com/leaven/archive/2010/11/17/1879679.html

  2. lsof,fuser,xargs,print0,cut,paste,cat,tac,rev,exec,{},双引号,单引号,‘(字符串中执行命令)

    cut用来从文本文件或标准输出中抽取数据列或者域,然后再用paste可以将这些数据粘贴起来形成相关文件. 粘贴两个不同来源的数据时,首先需将其分类,并确保两个文件行数相同.paste将按行将不同文件行 ...

  3. PHP webservice 的初接触

    webservice 现在是开始流行了,很多业务开启了这个功能.去年接触的一个金融类的项目有类似功能调用.当时没放心思研究,最两天试着接触了下,还真不错的.起步其实挺简单. 服务端的代码 server ...

  4. Linux下的信号机制

    2017-04-06 之前在看LinuxThreads线程模型的时候,看到该模型是通过信号实现线程间的同步,当时没有多想,直接当做信号量了,现在想起来真是汗颜……后来想想并不是那么回事,于是,就有了今 ...

  5. 图解HTTP之HTTPS详解

    背景:随着越来越多的主流网站已经使用了HTTPS,作为服务器端开发者,就必须了解HTTPS的优势与劣势. 在HTTP协议中有可能存在信息窃听或身份伪装等问题,而使用HTTPS通信机制可以有效地防止这些 ...

  6. Python性能优化的20条建议

    优化算法时间复杂度 算法的时间复杂度对程序的执行效率影响最大,在Python中可以通过选择合适的数据结构来优化时间复杂度,如list和set查找某一个元素的时间复杂度分别是O(n)和O(1).不同的场 ...

  7. 技术架构标杆(Certicom Security Architecture)对比思考——By Me at 20140408

    看到一家国外网络安全企业Certicom,官网链接:http://www.certicom.com/,可以作为很好的企业安全技术建构以及产品规划的标杆,下面我绘制了该公司的产品组合以及技术架构框图:

  8. Java中的反射[转载]

    转自:https://blog.csdn.net/sinat_38259539/article/details/71799078#commentBox 1.什么是反射? 反射是通过一个类可以知道其中所 ...

  9. mysql 系统变量和session变量

    mysql系统变量包括全局变量(global)和会话变量(session),global变量对所有session生效,session变量包括global变量.mysql调优必然会涉及这些系统变量的调整 ...

  10. c++中字符串反转的3种方法

    第一种:使用algorithm中的reverse函数 #include <iostream> #include <string> #include <algorithm& ...