测试机:Ubuntu14.04 x86_64
1. 代码:
#include <stdio.h>
void print(int a, int b, int c)
{
printf("a = %d\n", a);
printf("b = %d\n", b);
printf("c = %d\n", c);
}
void main(void)
{
int para1 = 5;
int para2 = 6;
int para3 = 7;
print(para1++, ++para2, para3);
printf("a = %d\n", para1);
printf("b = %d\n", para2);
printf("c = %d\n", para3);
}
2. 结果:
baoli@ubuntu:~/c$ ./a.out
a = 5
b = 7
c = 7
a = 6
b = 7
c = 7
3. 反汇编:
000000000040052d <print>:
40052d: 55 push %rbp
40052e: 48 89 e5 mov %rsp,%rbp
400531: 48 83 ec 10 sub $0x10,%rsp
400535: 89 7d fc mov %edi,-0x4(%rbp)
400538: 89 75 f8 mov %esi,-0x8(%rbp)
40053b: 89 55 f4 mov %edx,-0xc(%rbp)
40053e: 8b 45 fc mov -0x4(%rbp),%eax
400541: 89 c6 mov %eax,%esi
400543: bf 84 06 40 00 mov $0x400684,%edi
400548: b8 00 00 00 00 mov $0x0,%eax
40054d: e8 be fe ff ff callq 400410 <printf@plt>
400552: 8b 45 f8 mov -0x8(%rbp),%eax
400555: 89 c6 mov %eax,%esi
400557: bf 8c 06 40 00 mov $0x40068c,%edi
40055c: b8 00 00 00 00 mov $0x0,%eax
400561: e8 aa fe ff ff callq 400410 <printf@plt>
400566: 8b 45 f4 mov -0xc(%rbp),%eax
400569: 89 c6 mov %eax,%esi
40056b: bf 94 06 40 00 mov $0x400694,%edi
400570: b8 00 00 00 00 mov $0x0,%eax
400575: e8 96 fe ff ff callq 400410 <printf@plt>
40057a: c9 leaveq
40057b: c3 retq
000000000040057c <main>:
40057c: 55 push %rbp
40057d: 48 89 e5 mov %rsp,%rbp
400580: 48 83 ec 10 sub $0x10,%rsp
400584: c7 45 f4 05 00 00 00 movl $0x5,-0xc(%rbp)
40058b: c7 45 f8 06 00 00 00 movl $0x6,-0x8(%rbp)
400592: c7 45 fc 07 00 00 00 movl $0x7,-0x4(%rbp)
400599: 83 45 f8 01 addl $0x1,-0x8(%rbp)
40059d: 8b 45 f4 mov -0xc(%rbp),%eax
4005a0: 8d 50 01 lea 0x1(%rax),%edx
4005a3: 89 55 f4 mov %edx,-0xc(%rbp)
4005a6: 8b 55 fc mov -0x4(%rbp),%edx
4005a9: 8b 4d f8 mov -0x8(%rbp),%ecx
4005ac: 89 ce mov %ecx,%esi
4005ae: 89 c7 mov %eax,%edi
4005b0: e8 78 ff ff ff callq 40052d <print>
4005b5: 8b 45 f4 mov -0xc(%rbp),%eax
4005b8: 89 c6 mov %eax,%esi
4005ba: bf 84 06 40 00 mov $0x400684,%edi
4005bf: b8 00 00 00 00 mov $0x0,%eax
4005c4: e8 47 fe ff ff callq 400410 <printf@plt>
4005c9: 8b 45 f8 mov -0x8(%rbp),%eax
4005cc: 89 c6 mov %eax,%esi
4005ce: bf 8c 06 40 00 mov $0x40068c,%edi
4005d3: b8 00 00 00 00 mov $0x0,%eax
4005d8: e8 33 fe ff ff callq 400410 <printf@plt>
4005dd: 8b 45 fc mov -0x4(%rbp),%eax
4005e0: 89 c6 mov %eax,%esi
4005e2: bf 94 06 40 00 mov $0x400694,%edi
4005e7: b8 00 00 00 00 mov $0x0,%eax
4005ec: e8 1f fe ff ff callq 400410 <printf@plt>
4005f1: c9 leaveq
4005f2: c3 retq
4005f3: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
4005fa: 00 00 00
4005fd: 0f 1f 00 nopl (%rax)
4. 分析:
1. 对于para1++,先保存5到eax,后面会将eax保存到edi,所以edi也是5;然后再将值+1存到edx和rbp,所以edx和rbp都是6,由于在print中使用的是edi,所以打印是5
mov -0xc(%rbp),%eax
lea 0x1(%rax),%edx
mov %edx,-0xc(%rbp)
mov %eax,%edi
2. 对于++para2,先+1,然后保存到ecx和esi,由于在print使用esi,所以打印是7
addl $0x1,-0x8(%rbp)
mov -0x8(%rbp),%ecx
mov %ecx,%esi
3. 对于para3
mov -0x4(%rbp),%edx
4. 对于下列结果,由于使用的都是rpb,所以都是自增后的值
a = 6 //mov -0xc(%rbp),%eax
b = 7 //mov -0x8(%rbp),%eax
c = 7
注:上述参数传递没有使用入栈的方式,而是直接使用了寄存器传(eax、ecx、edx、esi、edi)递变量值,速度更快。
5. 总结:
1) 函数参数尽量不要使用++的形式,容易混淆,如果必须使用,使用++i形式。
2)++i作为函数参数时,传入函数内部的是自增后的值; i++作为函数参数时,传入函数内部的是原值(自增前)
3)无论是++i还是i++最后都会使值加1