美文网首页iOS 安全攻防
汇编-----函数的本质

汇编-----函数的本质

作者: 那时J花开 | 来源:发表于2018-05-07 22:22 被阅读0次

通过汇编代码我们可以探索函数的本质

  • 1: 如果函数内部没有调用其他函数, 那么sp不会进行偏移, 编译器会通过mov bp - N, 0x11的方式向栈中存入数据. 这是编译器所进行的优化.这个时候这个栈中的区域被称为 红色区域 不超过128个字节
    • 如果局部变量超过128个字节, 那么还是需要 sub sp, N来开辟栈空间
  int sum(int a, int b, int c) {
      int x = 10;
     // test();
      return a + b + c + x;
  }
可以看到, 如果函数内部没有调用其他函数, 并且所有参数的总字节数没有超过128个字节时 CPU并不会开辟新的空间,而是使用红色区域去存储变量
safe005`sum:
    0x103d90700 <+0>:  pushq  %rbp
    0x103d90701 <+1>:  movq   %rsp, %rbp
    0x103d90704 <+4>:  movl   %edi, -0x4(%rbp)
    0x103d90707 <+7>:  movl   %esi, -0x8(%rbp)
    0x103d9070a <+10>: movl   %edx, -0xc(%rbp)
->  0x103d9070d <+13>: movl   $0xa, -0x10(%rbp)
    0x103d90714 <+20>: movl   -0x4(%rbp), %edx
    0x103d90717 <+23>: addl   -0x8(%rbp), %edx
    0x103d9071a <+26>: addl   -0xc(%rbp), %edx
    0x103d9071d <+29>: addl   -0x10(%rbp), %edx
    0x103d90720 <+32>: movl   %edx, %eax
    0x103d90722 <+34>: popq   %rbp
    0x103d90723 <+35>: retq   
  • 2: 如果函数内部调用其他函数, 则必会通过 sub sp, N 来开辟栈空间
  void test() {
    
  }

  int sum(int a, int b, int c) {
      int x = 10;
      test();
      return a + b + c + x;
  }
以下是上边函数的汇编代码, 可以看到, 如果函数内部调用了其他函数, 则sp必会上移,开辟栈空间, 这时候 下一条指令的地址在 栈空间上一位, bp在上2位
    0x10417b6f0 <+0>:  pushq  %rbp
    0x10417b6f1 <+1>:  movq   %rsp, %rbp
    0x10417b6f4 <+4>:  subq   $0x10, %rsp
    0x10417b6f8 <+8>:  movl   %edi, -0x4(%rbp)
    0x10417b6fb <+11>: movl   %esi, -0x8(%rbp)
    0x10417b6fe <+14>: movl   %edx, -0xc(%rbp)
->  0x10417b701 <+17>: movl   $0xa, -0x10(%rbp)
    0x10417b708 <+24>: callq  0x10417b6e0               ; test at main.m:12
    0x10417b70d <+29>: movl   -0x4(%rbp), %edx
    0x10417b710 <+32>: addl   -0x8(%rbp), %edx
    0x10417b713 <+35>: addl   -0xc(%rbp), %edx
    0x10417b716 <+38>: addl   -0x10(%rbp), %edx
    0x10417b719 <+41>: movl   %edx, %eax
    0x10417b71b <+43>: addq   $0x10, %rsp
    0x10417b71f <+47>: popq   %rbp
    0x10417b720 <+48>: retq

栈帧

  • 栈帧指的是 sp和bp之间的空间 8086CPU中栈帧很明显就可以看到, 不过64位的CPU中 由于寄存器得到充分的运用, 所以栈帧不是每次函数调用都可以出现的

全局变量

image.png
  • 如上图所示, 全局变量相对于app来说, 其偏移地址一直是固定不变的, 而基地址是基于整个app在内存中的物理地址来随时改变的

if 判断

int a = 2;
        if (a == 1) {
            NSLog(@"a == 1");
        } else if (a == 2) {
            NSLog(@"a == 2");
        } else if (a == 3) {
            NSLog(@"a == 3");
        } else if (a == 4) {
            NSLog(@"a == 4");
        }
  0x1014926bb <+27>:  movl   $0x2, -0x14(%rbp) ;  赋值
->  0x1014926c2 <+34>:  cmpl   $0x1, -0x14(%rbp) ; cmp = cpmpare 比较
    0x1014926c6 <+38>:  movq   %rax, -0x20(%rbp)
    0x1014926ca <+42>:  jne    0x1014926e6               ; <+70> at main.m:21  ; jne: jump not equl 不等的时候跳转到0x1014926e6指令
    0x1014926d0 <+48>:  leaq   0x1989(%rip), %rax        ; @"a == 1"
    0x1014926d7 <+55>:  movq   %rax, %rdi
    0x1014926da <+58>:  movb   $0x0, %al
    0x1014926dc <+60>:  callq  0x101492a14               ; symbol stub for: NSLog
    0x1014926e1 <+65>:  jmp    0x101492750               ; <+176> at main.m:29
    0x1014926e6 <+70>:  cmpl   $0x2, -0x14(%rbp) 
    0x1014926ea <+74>:  jne    0x101492706               ; <+102> at main.m:23
    0x1014926f0 <+80>:  leaq   0x1989(%rip), %rax        ; @"a == 2"
    0x1014926f7 <+87>:  movq   %rax, %rdi
    0x1014926fa <+90>:  movb   $0x0, %al
    0x1014926fc <+92>:  callq  0x101492a14               ; symbol stub for: NSLog
    0x101492701 <+97>:  jmp    0x10149274b               ; <+171> at main.m
    0x101492706 <+102>: cmpl   $0x3, -0x14(%rbp)
    0x10149270a <+106>: jne    0x101492726               ; <+134> at main.m:25
    0x101492710 <+112>: leaq   0x1989(%rip), %rax        ; @"a == 3"
    0x101492717 <+119>: movq   %rax, %rdi
  • 以上代码是if判断的汇编实现, 问题来了, jne的时候 怎么判断是否相等而去跳转呢?
    • 是用标记寄存区来存放比较的结果的:


      image.png
      • 如上图, cmp前后 如果rflags值没有发生改变, 说明并不相等; 若发生改变, 说明相等

相关文章

  • 汇编-----函数的本质

    通过汇编代码我们可以探索函数的本质 1: 如果函数内部没有调用其他函数, 那么sp不会进行偏移, 编译器会通过mo...

  • 汇编-函数本质

    栈 栈:是一种具有特殊的访问方式的存储空间(后进先出, Last In Out Firt,LIFO)image.p...

  • 【8086汇编】-- 函数的本质

    一、函数的入参和返回值 上面展示了一个函数入参的方式有哪些,一般的cpu都是少量参数通过寄存器传参,当参数大于一定...

  • 【汇编】二、 函数本质

    002--函数本质 关于CPU的补充 寄存器 CPU除了有控制器、运算器还有寄存器。其中寄存器的作用就是进行数据的...

  • 汇编基础(二)函数的本质

    关于CPU 寄存器 CPU除了有控制器、运算器还有寄存器。其中寄存器的作用就是进行数据的临时存储。 CPU的运算速...

  • 汇编基础-探索函数本质

    初探 我们先看一下一个无参数无返回值的空函数,系统都干了啥。 void emptFun(){} 函数汇编 0x10...

  • 02-汇编基础(2)

    前言 本篇文章主要以汇编的角度,分析函数的本质,在分析函数的过程中,就会解决上篇文章最后的死循环问题。 一、基础知...

  • 函数调用本质

    文章来源:CoderHong 的博客 从反汇编角度窥探平时开发调用的函数或者方法的本质。平时我们编写的高级语言最终...

  • 程序调用过程和堆栈的关系,为什么要传地址而不传值

    bug.c 使用gdb调试,main函数反汇编的代码 swap函数的反汇编代码 在执行到call swap函数之前...

  • 反汇编学习笔记2 - 函数的本质

    函数本质 关于CPU的补充 寄存器 CPU除了有控制器、运算器还有寄存器。其中寄存器的作用就是进行数据的临时存储。...

网友评论

    本文标题:汇编-----函数的本质

    本文链接:https://www.haomeiwen.com/subject/irrbrftx.html