我有一个简单的函数序言(对于C程序的main(),没有参数),如下所示:
0x8048384 push ebp
0x8048385 mov ebp,esp
0x8048387 sub esp,0x18
0x804838a and esp,0xfffffff0
0x804838d mov eax,0x0
0x8048392 sub esp,eax
我很好奇,将eax设置为0然后从esp中减去它的目的是什么?这似乎浪费了指示。是否有其他gcc生成函数序言的例子,其中有更多含义(或者eax的值不是0)?
提前致谢!
编辑:完整的C程序(来自" The Explotation"书籍)如下。它只使用-g选项编译,使用gcc 3.3.6(是的,方式旧,但它来自虚拟机映像)。它应该是关于堆栈的一课。
void test_function(int a, int b, int c, int d)
{
int flag;
char buffer[10];
flag 31337;
buffer[0] = 'A';
}
int main()
{
test_function(1, 2, 3, 4);
}
编辑#2反汇编(gcc -g -S -masm = intel)提供:
.file "stack_example.c"
.intel_syntax
.file 1 "stack_example.c"
.section .debug_abbrev,"",@progbits
.Ldebug_abbrev0:
.section .debug_info,"",@progbits
.Ldebug_info0:
.section .debug_line,"",@progbits
.Ldebug_line0:
.text
.Ltext0:
.globl test_function
.type test_function, @function
test_function:
.LFB3:
.loc 1 1 0
push %ebp
.LCFI0:
mov %ebp, %esp
.LCFI1:
sub %esp, 40
.LCFI2:
.loc 1 5 0
.LBB2:
mov DWORD PTR [%ebp-12], 31337
.loc 1 6 0
mov BYTE PTR [%ebp-40], 65
.loc 1 7 0
leave
ret
.LBE2:
.LFE3:
.size test_function, .-test_function
.globl main
.type main, @function
main:
.LFB5:
.loc 1 9 0
push %ebp
.LCFI3:
mov %ebp, %esp
.LCFI4:
sub %esp, 24
.LCFI5:
and %esp, -16
mov %eax, 0
sub %esp, %eax
.loc 1 10 0
mov DWORD PTR [%esp+12], 4
mov DWORD PTR [%esp+8], 3
mov DWORD PTR [%esp+4], 2
mov DWORD PTR [%esp], 1
call test_function
.loc 1 11 0
leave
ret
.LFE5:
.size main, .-main
.section .debug_frame,"",@progbits
.Lframe0:
.long .LECIE0-.LSCIE0
.LSCIE0:
.long 0xffffffff
.byte 0x1
.string ""
.uleb128 0x1
.sleb128 -4
.byte 0x8
.byte 0xc
.uleb128 0x4
.uleb128 0x4
.byte 0x88
.uleb128 0x1
.align 4
.LECIE0:
.LSFDE0:
.long .LEFDE0-.LASFDE0
.LASFDE0:
.long .Lframe0
.long .LFB3
.long .LFE3-.LFB3
.byte 0x4
.long .LCFI0-.LFB3
.byte 0xe
.uleb128 0x8
.byte 0x85
.uleb128 0x2
.byte 0x4
.long .LCFI1-.LCFI0
.byte 0xd
.uleb128 0x5
.align 4
.LEFDE0:
.LSFDE2:
.long .LEFDE2-.LASFDE2
.LASFDE2:
.long .Lframe0
.long .LFB5
.long .LFE5-.LFB5
.byte 0x4
.long .LCFI3-.LFB5
.byte 0xe
.uleb128 0x8
.byte 0x85
.uleb128 0x2
.byte 0x4
.long .LCFI4-.LCFI3
.byte 0xd
.uleb128 0x5
.align 4
.LEFDE2:
.text
.Letext0:
.section .debug_info
.long 0x118
.value 0x2
.long .Ldebug_abbrev0
.byte 0x4
.uleb128 0x1
.long .Ldebug_line0
.long .Letext0
.long .Ltext0
.string "stack_example.c"
.string "/home/booksrc"
.string "GNU C 3.3.6 (Ubuntu 1:3.3.6-15ubuntu1)"
.byte 0x1
.uleb128 0x2
.long 0xd5
.byte 0x1
.string "test_function"
.byte 0x1
.byte 0x1
.byte 0x1
.long .LFB3
.long .LFE3
.byte 0x1
.byte 0x55
.uleb128 0x3
.string "a"
.byte 0x1
.byte 0x1
.long 0xd5
.byte 0x2
.byte 0x91
.sleb128 8
.uleb128 0x3
.string "b"
.byte 0x1
.byte 0x1
.long 0xd5
.byte 0x2
.byte 0x91
.sleb128 12
.uleb128 0x3
.string "c"
.byte 0x1
.byte 0x1
.long 0xd5
.byte 0x2
.byte 0x91
.sleb128 16
.uleb128 0x3
.string "d"
.byte 0x1
.byte 0x1
.long 0xd5
.byte 0x2
.byte 0x91
.sleb128 20
.uleb128 0x4
.string "flag"
.byte 0x1
.byte 0x2
.long 0xd5
.byte 0x2
.byte 0x91
.sleb128 -12
.uleb128 0x4
.string "buffer"
.byte 0x1
.byte 0x3
.long 0xdc
.byte 0x2
.byte 0x91
.sleb128 -40
.byte 0x0
.uleb128 0x5
.string "int"
.byte 0x4
.byte 0x5
.uleb128 0x6
.long 0xec
.long 0xfc
.uleb128 0x7
.long 0xec
.byte 0x9
.byte 0x0
.uleb128 0x5
.string "unsigned int"
.byte 0x4
.byte 0x7
.uleb128 0x5
.string "char"
.byte 0x1
.byte 0x6
.uleb128 0x8
.byte 0x1
.string "main"
.byte 0x1
.byte 0x9
.long 0xd5
.long .LFB5
.long .LFE5
.byte 0x1
.byte 0x55
.byte 0x0
.section .debug_abbrev
.uleb128 0x1
.uleb128 0x11
.byte 0x1
.uleb128 0x10
.uleb128 0x6
.uleb128 0x12
.uleb128 0x1
.uleb128 0x11
.uleb128 0x1
.uleb128 0x3
.uleb128 0x8
.uleb128 0x1b
.uleb128 0x8
.uleb128 0x25
.uleb128 0x8
.uleb128 0x13
.uleb128 0xb
.byte 0x0
.byte 0x0
.uleb128 0x2
.uleb128 0x2e
.byte 0x1
.uleb128 0x1
.uleb128 0x13
.uleb128 0x3f
.uleb128 0xc
.uleb128 0x3
.uleb128 0x8
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x27
.uleb128 0xc
.uleb128 0x11
.uleb128 0x1
.uleb128 0x12
.uleb128 0x1
.uleb128 0x40
.uleb128 0xa
.byte 0x0
.byte 0x0
.uleb128 0x3
.uleb128 0x5
.byte 0x0
.uleb128 0x3
.uleb128 0x8
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x49
.uleb128 0x13
.uleb128 0x2
.uleb128 0xa
.byte 0x0
.byte 0x0
.uleb128 0x4
.uleb128 0x34
.byte 0x0
.uleb128 0x3
.uleb128 0x8
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x49
.uleb128 0x13
.uleb128 0x2
.uleb128 0xa
.byte 0x0
.byte 0x0
.uleb128 0x5
.uleb128 0x24
.byte 0x0
.uleb128 0x3
.uleb128 0x8
.uleb128 0xb
.uleb128 0xb
.uleb128 0x3e
.uleb128 0xb
.byte 0x0
.byte 0x0
.uleb128 0x6
.uleb128 0x1
.byte 0x1
.uleb128 0x1
.uleb128 0x13
.uleb128 0x49
.uleb128 0x13
.byte 0x0
.byte 0x0
.uleb128 0x7
.uleb128 0x21
.byte 0x0
.uleb128 0x49
.uleb128 0x13
.uleb128 0x2f
.uleb128 0xb
.byte 0x0
.byte 0x0
.uleb128 0x8
.uleb128 0x2e
.byte 0x0
.uleb128 0x3f
.uleb128 0xc
.uleb128 0x3
.uleb128 0x8
.uleb128 0x3a
.uleb128 0xb
.uleb128 0x3b
.uleb128 0xb
.uleb128 0x49
.uleb128 0x13
.uleb128 0x11
.uleb128 0x1
.uleb128 0x12
.uleb128 0x1
.uleb128 0x40
.uleb128 0xa
.byte 0x0
.byte 0x0
.byte 0x0
.section .debug_pubnames,"",@progbits
.long 0x29
.value 0x2
.long .Ldebug_info0
.long 0x11c
.long 0x63
.string "test_function"
.long 0x104
.string "main"
.long 0x0
.section .debug_aranges,"",@progbits
.long 0x1c
.value 0x2
.long .Ldebug_info0
.byte 0x4
.byte 0x0
.value 0x0
.value 0x0
.long .Ltext0
.long .Letext0-.Ltext0
.long 0x0
.long 0x0
.section .note.GNU-stack,"",@progbits
.ident "GCC: (GNU) 3.3.6 (Ubuntu 1:3.3.6-15ubuntu1)"
答案 0 :(得分:0)
<强>更新强>
在看到源代码和完整的反汇编后,我不知道为什么这部分(mov eax, 0; sub esp,eax
)应该在那里。我认为没有合理的概括,编译器可能一直在瞄准。我确信,任何优化级别都会删除这些行,而新版本的gcc似乎会省略它们。
gcc的旧版本可能有这样的扩展函数头(虽然我看不出它们)或者这些命令是gcc内部表示的一些工件。也许有更多了解gcc历史的人可以回答这个......
旧回答
我不确定这一点,但可能的解释是
push ebp ; store stack pointer
mov ebp,esp ; create local frame
sub esp,0x18 ; make room for some variables + empty space to...
and esp,0xfffffff0 ; ... align the stack-pointer
mov eax,0x0 ; eax = sizeof(someClass)
sub esp,eax ; create room for one object on the aligned stack
这当然假设已经有一些优化(比如将对象大小减小到0,可能是一些内联,例如alloca
),但是gcc没有完全优化代码。可能是由于某些标志,如-Og
,-g
等。