2013-03-04 78 views
0

我在學習如何理解彙編程序中的c函數。我編譯使用以下的C程序 「GCC code.c -m32 -o代碼-S -fno堆疊保護器」瞭解程序集中的c函數

#include <stdio.h> 

void function(int a, int b, int c) 
{ 
    char buffer1[5]; 
    char buffer2[10]; 
} 

void main() 
{ 
    function(1, 2, 3); 
} 

的裝配臺輸出在以下:

 .section __TEXT,__text,regular,pure_instructions 
    .globl _function 
    .align 4, 0x90 
_function: 
    pushl %ebp 
    movl %esp, %ebp 
    subl $28, %esp 
    movl 16(%ebp), %eax 
    movl 12(%ebp), %ecx 
    movl 8(%ebp), %edx 
    movl %edx, -4(%ebp) 
    movl %ecx, -8(%ebp) 
    movl %eax, -12(%ebp) 
    addl $28, %esp 
    popl %ebp 
    ret 

    .globl _main 
    .align 4, 0x90 
_main: 
    pushl %ebp 
    movl %esp, %ebp 
    subl $24, %esp 
    movl $1, (%esp) 
    movl $2, 4(%esp) 
    movl $3, 8(%esp) 
    call _function 
    addl $24, %esp 
    popl %ebp 
    ret 


.subsections_via_symbols 

ESP和ebp寄存器不能相等,因爲在_main和_function中定義int a,b,c的偏移量是不同的。什麼行從ebp中減去4?

謝謝!

回答

1

沒有必要在任何地方減去4,因爲它是返回地址(給定32位體系結構)會消耗堆棧中的前4個字節。

因此,當引用堆棧上的元素時,$ 4的差異。返回ADRESS尚未被推之前call指令因此補償$ 0 $ 4和$ 8主要是細:

movl $1, (%esp) 
movl $2, 4(%esp) 
movl $3, 8(%esp) 

執行:

call _function 
在主

將推EIP的內容(因此增加esp 4。

作爲返回地址(消耗4個字節)的函數將位於堆棧頂部,正確的偏移量是 - $ 4, - $ 8和 - $ 12,這正是va梅毒在你的函數中使用:

movl %edx, -4(%ebp) 
movl %ecx, -8(%ebp) 
movl %eax, -12(%ebp) 
+0

但是,哪行代碼分配這些字節? – user1455332 2013-03-04 20:05:30

+1

這是'call'指令,它會自動將堆棧中的返回地址壓入堆棧,並將esp增加4.我會將其添加到答案中,以使事情清楚。 – mikyra 2013-03-04 20:07:57

2

調用函數通常是這樣的:

1)以外的功能,參數被壓入堆棧

subl $24, %esp 
movl $1, (%esp) 
movl $2, 4(%esp) 
movl $3, 8(%esp) 

2)在函數內部,在堆棧上分配空間以容納參數和局部變量。

subl $ 28%ESP

在這種情況下,你有3個整數和15個字符,共27個字節;這是對齊到一個4字節的邊界。

3)然後將參數複製到本地堆棧空間。

movl 16(%ebp), %eax 
movl 12(%ebp), %ecx 
movl 8(%ebp), %edx 
movl %edx, -4(%ebp) 
movl %ecx, -8(%ebp) 
movl %eax, -12(%ebp) 

在這裏,16(%EBP)和朋友的參數的地址外推,和-4(%EBP)在成被複制的那些值的新分配堆棧空間的地址。