1.基本类型的返回值
int add(int a, int b)
{
int c = 0;
b = c++;
return a+b;
}
int init()
{
int a = add(3, 4);
return a;
}
对应的汇编如下:
.file "list initialization.cpp"
.text
.globl _Z3addii
.type _Z3addii, @function
_Z3addii:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $16, %esp
movl $0, -8(%ebp)
movl -8(%ebp), %eax
movl %eax, -4(%ebp)
addl $1, -8(%ebp)
movl -4(%ebp), %eax
movl 8(%ebp), %edx
addl %edx, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size _Z3addii, .-_Z3addii
.globl _Z4initv
.type _Z4initv, @function
_Z4initv:
.LFB1:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
movl $4, 4(%esp)
movl $3, (%esp)
call _Z3addii
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE1:
.size _Z4initv, .-_Z4initv
.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
.section .note.GNU-stack,"",@progbits
函数默认以%eax作为返回值
看上面add函数的汇编代码,leave语句(即函数返回)的上一句代码:
addl %edx, %eax;即将a+b的值存到%eax寄存器中。接下来再看init中的下面两句汇编代码:
call _Z3addii;调用add函数,调用后%eax寄存器中的值就是add函数的返回值
movl %eax, -4(%ebp);将%eax寄存器的值存入局部变量a中
2.指针类型的返回值
int c = 0;
int* add(int a, int b)
{
c = a + b;
return &c;
}
int init()
{
int *a = add(3, 4);
return *a;
}
对应的汇编如下:
_Z3addii:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
movl 12(%ebp), %eax
movl 8(%ebp), %edx
addl %edx, %eax
movl %eax, c
movl $c, %eax
popl %ebp
.cfi_def_cfa 4, 4
.cfi_restore 5
ret
.cfi_endproc
.LFE0:
.size _Z3addii, .-_Z3addii
.globl _Z4initv
.type _Z4initv, @function
_Z4initv:
.LFB1:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
movl $4, 4(%esp)
movl $3, (%esp)
call _Z3addii
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
movl (%eax), %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
看上面的汇编可以发现,add函数利用语句:
movl $c, %eax;将全局变量c的地址赋值给%eax
init函数利用语句:
movl (%eax), %eax;将%eax寄存器值所代表的地址处的值赋值给%eax
3.引用类型的返回值
int c = 0;
int& add(int a, int b)
{
c = a + b;
return c;
}
int init()
{
int a = add(3, 4);
return a;
}
汇编代码如下:
_Z3addii:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
movl 12(%ebp), %eax
movl 8(%ebp), %edx
addl %edx, %eax
movl %eax, c
movl $c, %eax
popl %ebp
.cfi_def_cfa 4, 4
.cfi_restore 5
ret
.cfi_endproc
.LFE0:
.size _Z3addii, .-_Z3addii
.globl _Z4initv
.type _Z4initv, @function
_Z4initv:
.LFB1:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
subl $24, %esp
movl $4, 4(%esp)
movl $3, (%esp)
call _Z3addii
movl (%eax), %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
看上面汇编会发现,add函数还是利用语句:
movl $c, %eax;将全局变量c的地址作为返回值。
但不同的是调用它的函数利用语句:
movl (%eax), %eax;访问到c的值然后赋值给%eax;
结论:由此可以发现,函数的返回值都是通过%eax来传递的,且指针类型和引用类型的返回值都是地址值