如何判断在Linux上是否使用帧指针编译二进制文件?

时间:2011-03-23 02:08:09

标签: linux assembly

我在Linux中有二进制/库。如何确定使用帧指针编译它?

1 个答案:

答案 0 :(得分:9)

咱/布莱克伍宁:

使用/不使用framepointer优化编译一些简单的东西,并在反汇编输出上使用diff -u提供一些线索:

$ diff -u with*
--- with-fp 2011-03-23 09:49:29.366277002 +0000
+++ without-fp  2011-03-23 09:49:35.046277002 +0000
@@ -5,14 +5,12 @@
 Disassembly of section .text:

 00000000 <func>:
-   0:  55                      push   %ebp
+   0:  53                      push   %ebx
    1:  31 c0                   xor    %eax,%eax
-   3:  89 e5                   mov    %esp,%ebp
-   5:  53                      push   %ebx
-   6:  81 ec 00 04 00 00       sub    $0x400,%esp
-   c:  8b 4d 08                mov    0x8(%ebp),%ecx
-   f:  8d 9d fc fb ff ff       lea    -0x404(%ebp),%ebx
-  15:  8d 76 00                lea    0x0(%esi),%esi
+   3:  81 ec 00 04 00 00       sub    $0x400,%esp
+   9:  8b 8c 24 08 04 00 00    mov    0x408(%esp),%ecx
+  10:  89 e3                   mov    %esp,%ebx
+  12:  8d b6 00 00 00 00       lea    0x0(%esi),%esi
   18:  8b 14 81                mov    (%ecx,%eax,4),%edx
   1b:  89 14 83                mov    %edx,(%ebx,%eax,4)
   1e:  83 c0 01                add    $0x1,%eax
@@ -28,5 +26,4 @@
   3e:  75 f0                   jne    30 <func+0x30>
   40:  81 c4 00 04 00 00       add    $0x400,%esp
   46:  5b                      pop    %ebx
-  47:  5d                      pop    %ebp
-  48:  c3                      ret    
+  47:  c3                      ret    

您会看到多种更改:

  1. 带有画框指针的代码将始终包含两个指令push %ebp mov %esp, %ebp两个
    无帧码的代码可能(在所示的情况下,因为它没有使用%ebp寄存器来处理任何事情)有push %ebp不会拥有mov %esp, %ebp,因为没有必要初始化framepointer。
  2. 带有framepointers的代码访问堆栈相对于 framepointer 的参数,如图所示的mov 0x8(%ebp), %ecx
    无帧代码的代码相对于 stackpointer 是这样做的,并且附加了函数堆栈帧大小的偏移量,如mov 0x408(%esp), %ecx
    对于局部变量,情况也是如此,对于没有帧指针的代码,所显示的代码lea -0x404(%ebp), %ebx代表帧指针使用代码与mov %esp, %ebx(可能是lea 0x0(%esp), %ebx)。 / LI>
  3. 两者之间的寄存器分配可能会有一些变化,特别是如果代码变得足够复杂,使用 %ebp寄存器作为局部变量(显示的样本未显示)那)
  4. 编译器优化级别对生成的代码实际看起来有多大影响,但提到的这些特定项目(mov %esp, %ebp%ebp的使用 - 参数/局部变量的相对寻址)是在使用framepointers的代码中找到,如果使用-fomit-frame-pointer进行编译,则会丢失。