C语言函数调用

1: 指令


call instruction

tempEIP <-- EIP + DEST; (* DEST is rel32 *)
IF tempEIP is not within code segment limit THEN #GP(0); FI;
IF stack not large enough for a 4-byte return address
THEN #SS(0); FI;
Push(EIP);
EIP <-- tempEIP;   <==> pushl %eip


ret instruction

eip <-- pop   <==>    popl %eip


leave instruction

esp <-- ebp   <==>     movl %ebp, %esp
ebp <-- pop   <==>     popl %ebp


enter instruction
pushl %ebp
movl  %esp, %ebp
...
...

2: 调用过程


  • prepare to call  ==> prepare the input parameters, put them  into 8(%ebp), 12(%ebp), 16(%ebp), 20(%ebp) ...
  • call function  ==> pushl %eip

  • create stack  ==> enter
  • ==> pushl %ebp
  • ==> movl  %esp, %ebp

  • do something
  • destory stack  ==> leave
  •  ==> movl %ebp, %esp
  •                          ==> popl %ebp

  • ret                    ==> ret  ==> popl %eip

3: 堆栈

main -- ebp 
        -4
        -8   ==> ret = 28(%esp)
        -c   ==> second = 24(%esp)
        -10  ==> first = 20(%esp)
        -14
        -18
        -1c  ==> second - in parameter - 4(%esp)    ==>  12(%ebp)
esp --> -20  ==> first - in paramter - (%esp)       ==>  8(%ebp)

call sum:
esp --> EIP  ==> *(eip) = the instruction next to call sum

sum --  ebp  ==> ebp = esp; *(ebp) = prev_ebp
        -4   ==> ret = -4(%ebp)
        -8
        -c
        -10

4: C源代码


#include <stdio.h>

int sum(int a, int b)
{
    int ret;

    ret = a + b;

    return ret;
}


int main(int argc, char* argv[])
{
    int first = 5;
    int second = 6;
    int ret ;

    ret = sum(first, second);

    printf("ret = %d\n", ret);

    return 0;
}

5: 汇编代码


gcc -S -fno-asynchronous-unwind-tables stack.c 


	.file	"stack.c"
	.text
	.globl	sum
	.type	sum, @function
sum:
# 3. create the stack frame 
	pushl	%ebp
	movl	%esp, %ebp

# 4. alloc the stack space ==> ret = -4(%ebp)
	subl	$16, %esp

# 5. get the parameters from the higher stack    
	movl	12(%ebp), %eax
	movl	8(%ebp), %edx

# 6. calculation 
	addl	%edx, %eax

# 7. put the result into ret
	movl	%eax, -4(%ebp)

# 8. call convention, $eax is the return value 
	movl	-4(%ebp), %eax

# 9. destory stack frame 
	leave

# 10. popl %eip
	ret
	.size	sum, .-sum
	.section	.rodata
.LC0:
	.string	"ret = %d\n"
	.text
	.globl	main
	.type	main, @function
main:
    # create the stack frame 
	pushl	%ebp
	movl	%esp, %ebp

    # 16 bytes alignment
	andl	$-16, %esp

    # alloc stack space
	subl	$32, %esp

    # initialize the input parameters 
	movl	$5, 20(%esp)
	movl	$6, 24(%esp)

# 1. prepare the input parameters    
	movl	24(%esp), %eax
	movl	%eax, 4(%esp)

	movl	20(%esp), %eax
	movl	%eax, (%esp)

# 2. call the function sum  ==> push %eip
	call	sum

# 11. get the return value     
	movl	%eax, 28(%esp)

# prepare the input parameters for printf     
	movl	28(%esp), %eax
	movl	%eax, 4(%esp)
	movl	$.LC0, (%esp)
    
# call the function printf
	call	printf

# set the return value 
	movl	$0, %eax

# destroy the stack frame 
	leave

# popl %eip
	ret
	.size	main, .-main
	.ident	"GCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3"
	.section	.note.GNU-stack,"",@progbits


6: 二进制代码


objdump -d

0804841c <sum>:
 804841c:	55                   	push   %ebp
 804841d:	89 e5                	mov    %esp,%ebp
 804841f:	83 ec 10             	sub    $0x10,%esp
 8048422:	8b 45 0c             	mov    0xc(%ebp),%eax
 8048425:	8b 55 08             	mov    0x8(%ebp),%edx
 8048428:	01 d0                	add    %edx,%eax
 804842a:	89 45 fc             	mov    %eax,-0x4(%ebp)
 804842d:	8b 45 fc             	mov    -0x4(%ebp),%eax
 8048430:	c9                   	leave  
 8048431:	c3                   	ret    

08048432 <main>:
 8048432:	55                   	push   %ebp
 8048433:	89 e5                	mov    %esp,%ebp
 8048435:	83 e4 f0             	and    $0xfffffff0,%esp
 8048438:	83 ec 20             	sub    $0x20,%esp
 804843b:	c7 44 24 14 05 00 00 	movl   $0x5,0x14(%esp)
 8048442:	00 
 8048443:	c7 44 24 18 06 00 00 	movl   $0x6,0x18(%esp)
 804844a:	00 
 804844b:	8b 44 24 18          	mov    0x18(%esp),%eax
 804844f:	89 44 24 04          	mov    %eax,0x4(%esp)
 8048453:	8b 44 24 14          	mov    0x14(%esp),%eax
 8048457:	89 04 24             	mov    %eax,(%esp)
 804845a:	e8 bd ff ff ff       	call   804841c <sum>
 804845f:	89 44 24 1c          	mov    %eax,0x1c(%esp)
 8048463:	8b 44 24 1c          	mov    0x1c(%esp),%eax
 8048467:	89 44 24 04          	mov    %eax,0x4(%esp)
 804846b:	c7 04 24 10 85 04 08 	movl   $0x8048510,(%esp)
 8048472:	e8 79 fe ff ff       	call   80482f0 <printf@plt>
 8048477:	b8 00 00 00 00       	mov    $0x0,%eax
 804847c:	c9                   	leave  
 804847d:	c3                   	ret    
 804847e:	66 90                	xchg   %ax,%ax


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值