内容来源:
  《Debug Hack 中文版》#13
  汇编语言(指令简表)
  汇编指令对照表
  x86汇编指令集大全(带注释

实践
  ①创建源文件:vim assemble.c

#include<stdio.h>
int global;                                         //全局变量
int func_op(void)                                   //回调函数
{return 0;
}
void func(void)                                     //子功能函数
{unsigned long long val64 = 0;             //局部变量val64 = 0xffffeeeeddddcccc;                  //直接赋值十六进制方便阅读汇编代码global = 0x5555;                         //直接赋值十六进制方便阅读汇编代码
}
#define MAX_WORD 16                                 //宏定义
int main(void)                                      //主函数
{unsigned int i = 0;                           //局部变量char words[MAX_WORD]="Hello World";            //字符数组char word;                                    //字符变量int (*func_pointer)(void) = &func_op;        //函数指针赋值i = 0xabcd;                                 //直接赋值十六进制方便阅读汇编代码if(i !=0x1234)                              //if判断语句i=0;while(i == 0)                                //whlie循环语句i++;func();                                        //函数调用i = func_pointer();                          //函数指针调用for(i = 0;i < MAX_WORD-1;i++)             //for循环word = words[i];return 0;
}

  ②编译程序:gcc -Wall -o0 assemble.c -o assemble -m32,详细可查看:gcc认识
    -Wall:生成所有警告信息
    -o0:优化编译、连接,0是不优化
    -m32:现有环境为64位,想编译为32位。之前需下载对应的库:sudo apt-get install libc6-dev-i386 gcc-multilib g++-multilib
  ③objdump进行反汇编:objdump -d --no-show-raw-insn assemble
    --no-show-raw-insn:当分解指令时,不要打印指令字节。
    -d/--disassemble:显示来自objfile的机器指令的汇编助记符
PS:
  可通过man objdump查看帮助手册,/后输入对应的编译选项可找到对应的注释。n下移,N上移。

汇编程序解读

assemble:     file format elf32-i386
...
0804843b <func_op>:804843b:   push   %ebp804843c: mov    %esp,%ebp804843e:    mov    $0x0,%eax8048443:    pop    %ebp8048444: ret    08048445 <func>:8048445:   push   %ebp8048446: mov    %esp,%ebp8048448:    sub    $0x10,%esp804844b:   movl   $0x0,-0x8(%ebp)                  //4️⃣-28048452: movl   $0x0,-0x4(%ebp)8048459:  movl   $0xddddcccc,-0x8(%ebp)8048460:   movl   $0xffffeeee,-0x4(%ebp)8048467:   movl   $0x5555,0x804a020                //4️⃣-38048471: nop8048472: leave  8048473: ret    08048474 <main>:8048474:   lea    0x4(%esp),%ecx8048478:   and    $0xfffffff0,%esp804847b: pushl  -0x4(%ecx)804847e:   push   %ebp                             //分配栈帧工作804847f:    mov    %esp,%ebp                        //分配栈帧工作8048481:    push   %ecx8048482: sub    $0x24,%esp8048485:   mov    %gs:0x14,%eax804848b:    mov    %eax,-0xc(%ebp)804848e:  xor    %eax,%eax8048490:    movl   $0x0,-0x24(%ebp)8048497: movl   $0x6c6c6548,-0x1c(%ebp)804849e:  movl   $0x6f57206f,-0x18(%ebp)80484a5:  movl   $0x646c72,-0x14(%ebp)80484ac:    movl   $0x0,-0x10(%ebp)80484b3: movl   $0x804843b,-0x20(%ebp)80484ba:   movl   $0xabcd,-0x24(%ebp)              //1️⃣将0xabcd赋值给-0x24(%ebp)80484c1:  cmpl   $0x1234,-0x24(%ebp)              //2️⃣-1:比较两者之间差值   80484c8:  je     80484d7 <main+0x63>               //2️⃣-2:若相等则跳转该处80484ca: movl   $0x0,-0x24(%ebp)                 //2️⃣-3:若不等则对i赋值为080484d1:   jmp    80484d7 <main+0x63>               //2️⃣-4:直接跳转到该处80484d3:  addl   $0x1,-0x24(%ebp)                 //3️⃣-1:给i+180484d7:    cmpl   $0x0,-0x24(%ebp)                 //3️⃣-2:判断i等不等080484db:  je     80484d3 <main+0x5f>               //3️⃣-3:若相等则跳转到该处(3️⃣-1)80484dd:   call   8048445 <func>                 //4️⃣-1:调用func函数80484e2: mov    -0x20(%ebp),%eax80484e5: call   *%eax                            //5️⃣:函数指针的调用80484e7:    mov    %eax,-0x24(%ebp)80484ea: movl   $0x0,-0x24(%ebp)                 //6️⃣-1:i重新赋值为080484f1:  jmp    8048505 <main+0x91>               //6️⃣-2:无条件跳转到该处(6️⃣-9)80484f3:    lea    -0x1c(%ebp),%edx                 //6️⃣-3:将-0x1c(%ebp)地址存入edx中80484f6: mov    -0x24(%ebp),%eax                 //6️⃣-4:将-0x24(%ebp)值存入eax中80484f9:  add    %edx,%eax                        //6️⃣-5:将edx存的地址加到与eax的值相加后存入eax中80484fb:    movzbl (%eax),%eax                      //6️⃣-6:取eax地址的值存入eax中并加目标剩位填充080484fe:  mov    %al,-0x25(%ebp)                  //6️⃣-7:al为ax低八位,因为char只需8比特8048501:  addl   $0x1,-0x24(%ebp)                 //6️⃣-8:8048505: cmpl   $0xe,-0x24(%ebp)                 //6️⃣-9:比较i与MAX_WORD-18048509:   jbe    80484f3 <main+0x7f>               //6️⃣-10:比较结果若小于则跳到该处(6️⃣-3)继续循环804850b:  mov    $0x0,%eax                        //7️⃣8048510:   mov    -0xc(%ebp),%ecx8048513:  xor    %gs:0x14,%ecx804851a:    je     8048521 <main+0xad>804851c:   call   8048310 <__stack_chk_fail@plt>8048521:    add    $0x24,%esp8048524:   pop    %ecx8048525: pop    %ebp8048526: lea    -0x4(%ecx),%esp8048529:  ret    804852a: xchg   %ax,%ax804852c:  xchg   %ax,%ax804852e:  xchg   %ax,%ax
...

  1️⃣ movl S,D 指令:
    mov为传送指令,将S传给D(S->D).
    l表示(unsigned) int / long / char*类型 = 4个字节。
    -0x24(%ebp) 表示:从ebp寄存器中的地址值减去0x24后的地址值。 即i变量的地址。
  故:movl $0xabcd,-0x24(%ebp)= i = 0xabcd;
  2️⃣if语句:
  2️⃣-1: cmpl S1,S2 指令:
    cmp为比较指令[compare],将S1与S2之间的差(S1-S2).
  故cmpl $0x1234,-0x24(%ebp) = 0x1234-i
  2️⃣-2: je Label 指令:
  je为条件跳转指令:若比较结果为0(相等)则跳转到Lable处。不满足则继续往下执行。
  je 80484d7 <main+0x63>
  2️⃣-4: jmp Label 指令:
  jmp为无条件跳转指令:直接跳转到Lable处。
  3️⃣while语句:
  3️⃣-1: addl S,D 指令:
    add为加法指令,将D+S并存入D中(S+D->D).
  故addl $0x1,-0x24(%ebp)= i + 1
  4️⃣函数调用:
  4️⃣-1:call 指令:可跳转到函数后再返回。即此时会跳转到func()函数处。
  4️⃣-2:可看出每次赋值都执行了两次,这是因为在32位操作系统上定义64比特变量都会这样。这是给局部变量进行赋值,以ebp寄存器的偏移量来表示,值写进了栈内的地址。
  4️⃣-3:这边是给全局变量赋值,可看到这边地址的表示方法与上面局部变量的表示方法不同,是直接以地址值的形式。
  5️⃣函数指针的调用:
  调用函数指针func_op(),函数指针保存在eax中,要想*%eax这样加上星号(*)
  6️⃣for循环:
  6️⃣-3:lea &S,D 指令:
    lea为目的地址传送指令,将S的地址传入D寄存器中(&S–>D)【mov S,D的区别是lea是取S的地址】
  6️⃣-6:movzbl &S,D 指令:
    书中语句为movzbl -0x20(%ebp,%eax,1),%eax,-0x20(%ebp,%eax,1),此为伸缩化变址寻址含义:*( -0x20+ebp+eax*1)
    对应程序中的(6️⃣-3)+(6️⃣-4)+(6️⃣-5)+(6️⃣-6)这四步。实现:将word(-0x20%ebp)的第i(%eax)位上1字节赋值给eax,也就是word=word[i]
    movzbl指令为零扩展,负责拷贝一个字节并用0填充气目的操作数中的其他位。
  7️⃣范围值设置:
    return语句,给返回值赋0.
    return语句的返回值为int等4字节一下的情况,则要将返回值放到eax中,是以eax寄存器为通用寄存器的。

gdb学习汇编(三)相关推荐

  1. GDB调试汇编堆栈过程的学习

    GDB调试汇编堆栈过程的学习 分析过程 这是我的C源文件: 1.安装32位兼容包 2.使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用 ...

  2. 【转】学习汇编前你应该知道的知识

    转载地址:http://www.zxbc.cn/html/20070611/22772.html 1.汇编需要什么工具和程序,到哪里下载?     目前阶段,汇编程序仅需要两个程序就够了.masm.e ...

  3. 一步步学习汇编(8)之指令

    要理解ret,retf,call指令,必须要先理清以下汇编基础知识: 一.             [bx]和内存单元<?xml:namespace prefix = o ns = " ...

  4. “C语言” 读书札记(五)之[让我们一起学习汇编吧!(段)]

    "C语言" 读书札记(五)之[让我们一起学习汇编吧!(段)] 介绍 这几天满脑子都是寄存器,存储器--主要是卡在汇编语言上了,所以博文进度比较缓慢. 今天就先讲讲如何定义数据元素吧 ...

  5. 学习汇编前你应该知道的知识

    1.汇编需要什么工具和程序,到哪里下载?     目前阶段,汇编程序仅需要两个程序就够了.masm.exe,link.exe. 前者是编译程序,后者是链接程序.另外,为了验证和调试程序,还需要一个程序 ...

  6. geopandas学习(三) 文件IO

    geopandas学习(三) 文件IO 文章参考:参考 1.矢量文件的读入 geopandas将fiona作为操纵矢量数据读写功能的后端. 使用geopandas.read_file()读取对应类型文 ...

  7. 强化学习(三) - Gym库介绍和使用,Markov决策程序实例,动态规划决策实例

    强化学习(三) - Gym库介绍和使用,Markov决策程序实例,动态规划决策实例 1. 引言 在这个部分补充之前马尔科夫决策和动态规划部分的代码.在以后的内容我会把相关代码都附到相关内容的后面.本部 ...

  8. Java IO流学习总结三:缓冲流-BufferedInputStream、BufferedOutputStream

    Java IO流学习总结三:缓冲流-BufferedInputStream.BufferedOutputStream 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/ ...

  9. SIGSEGV 和 SIGBUS gdb看汇编

    参考这篇文章: http://blog.chinaunix.net/uid-24599332-id-2122898.html SIGBUS和SIGSEGV也许是我们在平时遇到的次数最多的两个内存错误信 ...

最新文章

  1. 关于rms,打开文档的时候提示您没有权限打开文档,因为您的权限已过期
  2. oracle 动态sql列转行_SQL优化笔记分享:34条实用经验可别错过!
  3. 那些做了十年的老开发都去哪了?
  4. 单例模式示例_单例设计模式示例
  5. 中怎样载入选区_PS----关于选区的选取
  6. 关于 shell 脚本编程的10 个最佳实践
  7. python实现knn分类_knn分类算法底层实现(python)
  8. 天正多条线段长度lisp下载_预习丨人教版六年级数学(上册)全册知识要点梳理,可下载...
  9. Tensorflow:可视化学习TensorBoard
  10. d3.js(v5.7)的node与数据匹配(自动匹配扩展函数)
  11. 统计自然语言处理(第2版)目录
  12. 【UV打印机】PrintExp打印软件教程(九)-厂家模式(中)
  13. 西安北邮html5,西安北邮在线菜鸟的IT梦,给我一个支点,我就能撬动地球
  14. Unity 性能优化之合批
  15. 教程篇(7.0) 06. FortiGate基础架构 单点登录(FSSO) ❀ Fortinet 网络安全专家 NSE 4
  16. paper 94:视觉领域博客资源1之中国部分
  17. 反恐精英在线服务器名称,反恐精英1.6 国内服务器IP大全
  18. 详解Unity中的Nav Mesh新特性|导航寻路系统 (二)
  19. 华为、微软、瑞幸、维达、奈飞、爱彼迎等公司高管变动
  20. su 命令无法切换用户

热门文章

  1. 想用好大数据,你需要先了解这些事
  2. linux运维常见英文报错中文翻译(菜鸟必知)
  3. Centos 查看 登录 登出 重启 日志
  4. 거든---表示条件,后接祈使,劝诱,意志语句
  5. ActiveMQ持久化方式
  6. Linux常用的基本命令13
  7. LoadRunner参数化---数据文件属性 之 数据分配方法和数据更新方法
  8. 史上最详细MySQL5.5复制配置步骤,与以前版本的有所不同
  9. 《Mining Text Data》阅读笔记---第1章 An Introduction to Text Mining
  10. python读取文本数据--完善中