x86_64及aarch64架构传参规则

1. x86_64参数传递

x86_64汇编语言函数通过rdi、rsi、rdx、rcx、r8、r9(edi、esi、edx、ecx、r8、r9)传递。即:

  • 1个参数: rdi(edi)
  • 2个参数: rdi、rsi(edi、rsi)
  • 3个参数: rdi、rsi、rdx(edi、esi、edx)
  • 4个参数: rdi、rsi、rdx、rcx(edi、esi、edx、ecx)
  • 5个参数: rdi、rsi、rdx、rcx、r8(edi、esi、edx、ecx、r8)
  • 6个参数: rdi、rsi、rdx、rcx、r8、r9(edi、esi、edx、ecx、r8、r9)

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

x64架构下一共有16个通用寄存器, 以’r’开头。而32位系统的寄存器是以’e’开头的. 实际上64位的系统架构也兼容了32位系统。我们仍然可以在64位系统中使用如’eax’等寄存器, 表示只使用’rax’寄存器的低32位, 其剩余的高32位会自动补全

/* x86_64.c */
# include<stdio.h>

void fun1(int a)
{
    
    }
void fun2(int a,int b)
{
    
    }
void fun3(int a,int b,int c)
{
    
    }
void fun4(int a,int b,int c,int d)
{
    
    }
void fun5(int a,int b,int c,int d,int e)
{
    
    }
void fun6(int a,int b,int c,int d,int e,int f)
{
    
    }
void fun7(int a,int b,int c,int d,int e,int f, int g)
{
    
    }


void main()
{
    
    
    int a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8;

    fun1(a);
    fun2(a,b);
    fun3(a,b,c);
    fun4(a,b,c,d);
    fun5(a,b,c,d,e);
    fun6(a,b,c,d,e,f);
    fun7(a,b,c,d,e,f,g);
}

执行 gcc -S x86_64.c

	movl	-4(%rbp), %eax
	movl	%eax, %edi
	call	fun1
	movl	-8(%rbp), %edx
	movl	-4(%rbp), %eax
	movl	%edx, %esi
	movl	%eax, %edi
	call	fun2
	movl	-12(%rbp), %edx
	movl	-8(%rbp), %ecx
	movl	-4(%rbp), %eax
	movl	%ecx, %esi
	movl	%eax, %edi
	call	fun3
	movl	-16(%rbp), %ecx
	movl	-12(%rbp), %edx
	movl	-8(%rbp), %esi
	movl	-4(%rbp), %eax
	movl	%eax, %edi
	call	fun4
	movl	-20(%rbp), %edi
	movl	-16(%rbp), %ecx
	movl	-12(%rbp), %edx
	movl	-8(%rbp), %esi
	movl	-4(%rbp), %eax
	movl	%edi, %r8d
	movl	%eax, %edi
	call	fun5
	movl	-24(%rbp), %r8d
	movl	-20(%rbp), %edi
	movl	-16(%rbp), %ecx
	movl	-12(%rbp), %edx
	movl	-8(%rbp), %esi
	movl	-4(%rbp), %eax
	movl	%r8d, %r9d
	movl	%edi, %r8d
	movl	%eax, %edi
	call	fun6
	movl	-24(%rbp), %r9d
	movl	-20(%rbp), %r8d
	movl	-16(%rbp), %ecx
	movl	-12(%rbp), %edx
	movl	-8(%rbp), %esi
	movl	-4(%rbp), %eax
	movl	-28(%rbp), %edi
	pushq	%rdi
	movl	%eax, %edi
	call	fun7

2. aarch64参数传递

aarch64汇编语言函数前8个参数使用x0-x7寄存器(或低32位w0-w7寄存器)传递, 多于8个的参数均通过堆栈传递

/* aarch64.c */
# include<stdio.h>

void fun1(int a)
{
    
    }
void fun2(int a,int b)
{
    
    }
void fun3(int a,int b,int c)
{
    
    }
void fun4(int a,int b,int c,int d)
{
    
    }
void fun5(int a,int b,int c,int d,int e)
{
    
    }
void fun6(int a,int b,int c,int d,int e,int f)
{
    
    }
void fun7(int a,int b,int c,int d,int e,int f,int g)
{
    
    }
void fun8(int a,int b,int c,int d,int e,int f,int g,int h)
{
    
    }
void fun9(int a,int b,int c,int d,int e,int f,int g,int h,int i)
{
    
    }


void main()
{
    
    
	int a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9;
	fun1(a);
	fun2(a,b);
	fun3(a,b,c);
	fun4(a,b,c,d);
	fun5(a,b,c,d,e);
	fun6(a,b,c,d,e,f);
	fun7(a,b,c,d,e,f,g);
	fun8(a,b,c,d,e,f,g,h);
	fun9(a,b,c,d,e,f,g,h,i);
}


执行 gcc -S aarch64.c

	ldr	w0, [sp, 76]
	bl	fun1
	ldr	w1, [sp, 72]
	ldr	w0, [sp, 76]
	bl	fun2
	ldr	w2, [sp, 68]
	ldr	w1, [sp, 72]
	ldr	w0, [sp, 76]
	bl	fun3
	ldr	w3, [sp, 64]
	ldr	w2, [sp, 68]
	ldr	w1, [sp, 72]
	ldr	w0, [sp, 76]
	bl	fun4
	ldr	w4, [sp, 60]
	ldr	w3, [sp, 64]
	ldr	w2, [sp, 68]
	ldr	w1, [sp, 72]
	ldr	w0, [sp, 76]
	bl	fun5
	ldr	w5, [sp, 56]
	ldr	w4, [sp, 60]
	ldr	w3, [sp, 64]
	ldr	w2, [sp, 68]
	ldr	w1, [sp, 72]
	ldr	w0, [sp, 76]
	bl	fun6
	ldr	w6, [sp, 52]
	ldr	w5, [sp, 56]
	ldr	w4, [sp, 60]
	ldr	w3, [sp, 64]
	ldr	w2, [sp, 68]
	ldr	w1, [sp, 72]
	ldr	w0, [sp, 76]
	bl	fun7
	ldr	w7, [sp, 48]
	ldr	w6, [sp, 52]
	ldr	w5, [sp, 56]
	ldr	w4, [sp, 60]
	ldr	w3, [sp, 64]
	ldr	w2, [sp, 68]
	ldr	w1, [sp, 72]
	ldr	w0, [sp, 76]
	bl	fun8
	ldr	w0, [sp, 44]
	str	w0, [sp]
	ldr	w7, [sp, 48]
	ldr	w6, [sp, 52]
	ldr	w5, [sp, 56]
	ldr	w4, [sp, 60]
	ldr	w3, [sp, 64]
	ldr	w2, [sp, 68]
	ldr	w1, [sp, 72]
	ldr	w0, [sp, 76]
	bl	fun9

猜你喜欢

转载自blog.csdn.net/hbuxiaofei/article/details/125160763