zoukankan      html  css  js  c++  java
  • 二进制分析-栈

    x86只有8个通用寄存此供使用(eax, ebx, ecx, edx, ebp, esp, esi, edi)。x64将它们扩展为64位(前缀由“e”变更为“r”),
    并且新增了8个寄存器(r8, r9, r10, r11, r12, r13, r14, r15)。
    由于x86下一些寄存器有特殊的用途和意义而不是真正意义上的“通用”(尤其是ebp和esp寄存器),
    使得这些新增的特性产生的效用远不止是变大变多。

    从ABI来看,函数开始的6个整数或指针类型的参数将通过寄存器传递参数,
    第一个参数保存在rdi中,第二个保存在rsi中,接下来依次保存在rdx,rcx,r8,r9。
    从第7个参数开始,接下来的所有参数都将通过栈传递。

    值得注意的是,生成的汇编代码中函数 printf()被替换成了 puts(),这是因为当 printf()只有单一
    参数时,与 puts()是十分类似的,于是 GCC 的优化策略就将其替换以提高性能。
    leave # (mov esp, ebp; pop ebp)

    对于 x86-64 的程序,前 6 个参数分别通过 rdi、rsi、rdx、rcx、r8 和 r9 进行传递,剩余参数才像
    x86 一样从后向前依次压栈。除此之外,我们还发现 func()没有下移 rsp 开辟栈空间的操作,导致 rbp
    和 rsp 的值是相同的,其实这是一项编译优化:根据 AMD64 ABI 文档的描述,rsp 以下 128 字节的
    区域被称为 red zone,这是一块被保留的内存,不会被信号或者中断所修改。于是,func()作为叶子
    函数就可以在不调整栈指针的情况下,使用这块内存保存临时数据。
    在更极端的优化下,rbp 作为栈基址其实也是可以省略的,编译器完全可以使用 rsp 来代替,从
    而减少指令数量。GCC 编译时添加参数“-fomit-frame-pointer”即可。
    https://bbs.pediy.com/thread-200575.htm

  • 相关阅读:
    aarch64_p1
    aarch64_o2
    aarch64_o1
    aarch64_n3
    aarch64_n2
    aarch64_n1
    aarch64_m3
    aarch64_m2
    aarch64_m1
    aarch64_l3
  • 原文地址:https://www.cnblogs.com/CSE-kun/p/14841518.html
Copyright © 2011-2022 走看看