sub esp的目的是什么,eax在函数序言中?

时间:2014-04-23 20:34:17

标签: gcc assembly

我有一个简单的函数序言(对于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)"

1 个答案:

答案 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等。