#include <stdio.h>
int fun(long i){
return i + 1;
}
int main(){
long a = 3;
long b = fun(a);
return b;
}
对于fun函数,其汇编代码如下
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq %rdi, -8(%rbp) 通过rdi传参,若形参类型为int,则通过edi传参
movq -8(%rbp), %rax 将内存中的i移到寄存器rax中
addl $1, %eax 由于返回值是int类型,故用eax和1相加,eax是rax的低位部分,
x86、x64通过eax、rad传递返回值,当x86返回值为64位整数类型时,采用低32位eax、高32位edx存放返回值
popq %rbp
.cfi_def_cfa 7, 8
ret
main函数中
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movq $3, -16(%rbp)
movq -16(%rbp), %rax
movq %rax, %rdi
call fun 函数调用
cltq 函数返回值的类型是int,而b为long,需要强制类型转换
cltq将eax扩张为rax,与movslq %eax,%rax有一样的作用,
在c语言中通常表示为int到long的强制类型转换
movq %rax, -8(%rbp)
movq -8(%rbp), %rax 由于返回值是long类型,故用rax传递返回值
leave
.cfi_def_cfa 7, 8
ret
再看另一个例子
long fun(int i){
return i + 1;
}
int main(){
long a = 3;
int b = fun(a);
return b;
}
fun函数的主要汇编代码如下
movl %edi, -4(%rbp)
movl -4(%rbp), %eax
addl $1, %eax
cltq 返回值为long类型,而i+1为int,用cltq进行强制类型转换
main函数的主要汇编代码如下
movq $3, -8(%rbp)
movq -8(%rbp), %rax a为long类型,故加载到rax而不是eax
movl %eax, %edi 实参a为long类型,形参i为int,故取eax即rax的低32位,将其放入edi进行传参
call fun
movl %eax, -12(%rbp)
movl -12(%rbp), %eax
当函数实参和形参都是long类型时,main函数的主要汇编代码则如下
movq $3, -8(%rbp)
movq -8(%rbp), %rax
movl %rax, %rdi 实参形参都为long类型,故为rax
call fun
总结:
int强转为long,用cltq
cltq将eax扩张为rax,与movslq %eax,%rax有一样的作用,在c语言中通常表示为int到long的强制类型转换
long强转为int,此处假设此long类型的变量存在rax里,则要使用这个变量时,直接用eax
eax是rax的低位部分
通过寄存器传递返回值时,对于x86系统,若返回值为32位整型,则用eax,若为64位整型,则用eax存放低32位,edx存放高32位;浮点类型的返回值则采用浮点寄存器st(0)。对于x64系统,对于整型数据,用rax存放返回值;浮点类型的返回值也采用浮点寄存器st(0)。