C语言调用函数时参数是使用栈还是寄存器

本文探讨了C语言在32位和64位程序中函数参数传递的方式。在32位系统中,参数通过栈传递;而在64位系统中,前6个参数使用寄存器,超出部分则使用栈。通过反汇编代码验证了这一结论,展示了不同参数数量下参数如何在寄存器和栈之间分配。
摘要由CSDN通过智能技术生成

一、结论

网上的文章有的说C语言调用函数参数使用栈传递,有的说使用寄存器传递。那么到底参数是使用栈还是寄存器呢?

先说结论:

  • 32位程序使用栈传递
  • 64位程序根据参数的个数而不同
    • 参数1~6个,使用寄存器传递
    • 参数大于6个,多出来的参数使用栈传递

二、验证

1. 32位程序
  1. 源代码:
// main.c
void fun(int a, int b)
{
    a += 1;
    b += 1;
}
int main(void)
{
    fun(1, 2);
    return 0;
}
  1. 生成32位的程序:
gcc  -g -m32 main.c -o main32
  1. 使用gdb调试:
gdb main32
  1. 在gdb中,查看main函数反汇编代码(在gdb中输入disassemble main):

image-20210529165145850

注意,我这里设置了gdb的汇编为Intel 汇编,如果没有设置,gdb默认使用AT&T汇编风格。

可以看出:

  • 汇编代码先把0x2压栈,然后把0x1压栈
  • 对应C源码中,就是参数从右到左入栈
2. 64位程序

64位C程序,参数个数不同,传参方式不同。

2.1 参数小于等于6个
  1. 源代码(还是上面的代码):
// main.c
void fun(int a, int b)
{
    a += 1;
    b += 1;
}
int main(void)
{
    fun(1, 2);
    return 0;
}
  1. 生成64位的可执行程序:
gcc -m64 -g main.c -o main64

我的gcc默认生成64位的,可以不用-64指定

  1. 使用gdb调试
gdb main64
  1. 在gdb中查看main函数的反汇编代码

image-20210529170049994

如上图可以看出:

  • 参数传入了寄存器esi和edi
2.2 参数大于6个
  1. 源代码
void fun(int a, int b, int c, int d, int e, int f, int g)
{
    a += 1;
    b += 1;
    c += 1;
    d += 1;
    e += 1;
    f += 1;
    g += 1;
}
int main(void)
{
    fun(1, 2, 3, 4, 5, 6, 7);
    return 0;
}
  1. 生成64位程序
gcc -m64 -g main.c -o main64
  1. gdb调试
gdb main64
  1. 查看main函数汇编代码

image-20210529170903032

可以看出:

  • 传递了7个参数,一个是用栈,其他6个是用的寄存器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值