C语言参数传递所使用的寄存器

12 篇文章 1 订阅

探索下C语言的函数是如何传递参数的,寄存器?栈?,何时使用寄存器,使用哪些寄存器,什么时候使用栈来传递参数。这是容易疑惑的地方。

用gcc编译C程序,看看C语言是如何传递参数的。同时用到了edb调试器。使用的操作系统是linux 64位。

思路是编写一个简单的函数,具有个数不同的参数。函数没有具体的意义,纯粹是为了探索C语言的函数是如何传递参数的。

  • 函数有1个参数
// a.c
// gcc a.c
#include <stdio.h>
void f(int a){
	a = a + 1;
}

int main(int argc, char *argv[]){
	f(2);
	return 0;
}

上面的函数f很简单,只有一个参数。使用edb运行编译后生成的程序。

edb --run a.out

点击Run。下面的截图是汇编代码,包括地址,指令和汇编代码。

push rbp

mov rbp, rsp

sub rsp, 0x10

首先将rbp压到栈中,为了保存原始的rbp值,然后rbp=rsp,保存rsp的值到rbp中,然后rsp减去0x10,rsp是指向栈顶,栈是向低地址增长的,rsp减去0x10,也就是留出了栈空间。

mov [rbp-4], edi

mov [rbp-0x10], rsi

rbp保存这旧的rsp,上面这两行代码将edi和rsi保存到栈中,说明后面可能用到这两个寄存器。

mov edi, 2

将立即数2到edi中,在main函数中,调用了f(2),因此edi用来传递函数参数。

call 0x5647db259125

调用函数f,也就是图片中的第一行汇编代码。

结论:当函数有一个参数时,使用edi传递参数。

后面更多参数时,不会这样详细,只找到是如何传递函数参数的。

  • 函数有2个参数
#include <stdio.h>
void f(int a, int b){
	a = a + 1;
	b = b + 1;
}

int main(int argc, char *argv[]){
	f(1,2);
	return 0;
}

mov esi, 2

mov edi, 1

第1个参数通过寄存器edi传递,第2个参数通过esi传递。

结论:函数有2个参数,通过ediesi传递。如果参数大小是64位,8字节的,则通过rdirsi传递参数。

  • 函数有4个参数
#include <stdio.h>
void f(int a, int b, int c, int d){
	a = a + 1;
	b = b + 1;
	c = c + 1;
	d = d + 1;
}

int main(int argc, char *argv[]){
	f(1,2,3,4);
	return 0;
}

当函数有4个参数时,使用edi,esi,edx,ecx传递参数。如果是8个字节,则通过rdi,rsi,rdx,rcx传递参数。

  • 函数有6个参数
#include <stdio.h>
void f(int a, int b, int c, int d, int e, int ff){
	a = a + 1;
	b = b + 1;
	c = c + 1;
	d = d + 1;
	e = e + 1;
	ff = ff + 1;
}

int main(int argc, char *argv[]){
	f(1,2,3,4,5,6);
	return 0;
}

当函数有6个参数时,使用edi,esi,edx,ecx,r8d,r9d传递参数。在x86-64中,多了这几个寄存器:r8,r9,r10,r11,r12,r13,r14,r15,r16,都是8字节的,r8d表示r8的低32位。r8w和r8b则分别表示低16位和低8位。

结论:使用rdi,rsi,rdx,rcx,r8,r9传递参数。如果不是64位,则使用对应长度的寄存器。

到这里还没有使用栈传递参数。到底参数个数到多少个才会使用栈传递参数呢?

实验发现,第7个参数会使用栈来传递。

  • 函数有8个参数
#include <stdio.h>
void f(int a, int b, int c, int d, int e, int f6, int f7, int f8){
	a = a + 1;
	b = b + 1;
	c = c + 1;
	d = d + 1;
	e = e + 1;
}

int main(int argc, char *argv[]){
	f(1,2,3,4,5,6,7,8);
	return 0;
}

参数7和8通过栈传递,注意压栈顺序,push 8; push 7,说明是从右往左入栈的。

结论:当参数个数小于等于6个时,使用寄存器rdi,rsi,rdx,rcx,r8,r9,从第7个参数开始通过栈传递,顺序为从右往左入栈。

 

  • 8
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值