ARMv8——函数调用参数传递

参考链接

ARM处理器函数调用时的参数传递

函数调用参数传递

对于 ARM32 架构,函数调用时前4个参数用通用寄存器 (R0~R3),其余的参数的用栈传递

对于 ARM64 架构,函数调用时前8个参数用通用寄存器 (X0~X7),其余的参数的用栈传递

#include <stdio.h>

int func(int a, int b, int c, int *e, int f, int *g, int h, int i, int j, int *k)
{
    return a + b + c + *e + f + *g + h + i + j + *k;
}

int main(int argc, const char *argv[])
{
    int e = 4, g=6, k=10;

    printf("%d\n", func(1, 2, 3, &e, 5, &g, 7, 8, 9, &k));

    return 0;
}

分别使用32位和64位交叉编译器生成汇编文件

ARM32 架构

@ arm-linux-gnueabihf-gcc -S main.c -o main32.s

	.arch armv7-a
	.eabi_attribute 28, 1
	.eabi_attribute 20, 1
	.eabi_attribute 21, 1
	.eabi_attribute 23, 3
	.eabi_attribute 24, 1
	.eabi_attribute 25, 1
	.eabi_attribute 26, 2
	.eabi_attribute 30, 6
	.eabi_attribute 34, 1
	.eabi_attribute 18, 4
	.file	"main.c"
	.text
	.align	1
	.global	func
	.syntax unified
	.thumb
	.thumb_func
	.fpu vfpv3-d16
	.type	func, %function @ 将符号func定义为函数类型
func:
	@ args = 24, pretend = 0, frame = 16
	@ frame_needed = 1, uses_anonymous_args = 0
	@ link register save eliminated.
	push	{r7} @ 将寄存器r7值压入堆栈
	sub	sp, sp, #20 @ 在栈上分配20字节空间
	add	r7, sp, #0 
	str	r0, [r7, #12]
	str	r1, [r7, #8]
	str	r2, [r7, #4]
	str	r3, [r7]
	ldr	r2, [r7, #12]
	ldr	r3, [r7, #8]
	add	r2, r2, r3
	ldr	r3, [r7, #4]
	add	r2, r2, r3
	ldr	r3, [r7]
	ldr	r3, [r3]
	add	r2, r2, r3
	ldr	r3, [r7, #24]
	add	r2, r2, r3
	ldr	r3, [r7, #28]
	ldr	r3, [r3]
	add	r2, r2, r3
	ldr	r3, [r7, #32]
	add	r2, r2, r3
	ldr	r3, [r7, #36]
	add	r2, r2, r3
	ldr	r3, [r7, #40]
	add	r2, r2, r3
	ldr	r3, [r7, #44]
	ldr	r3, [r3]
	add	r3, r3, r2
	mov	r0, r3
	adds	r7, r7, #20
	mov	sp, r7
	@ sp needed
	ldr	r7, [sp], #4
	bx	lr @ 返回地址保存在 lr 寄存器中,bx指令返回到调用函数地方
	.size	func, .-func
	.section	.rodata
	.align	2
.LC0:
	.ascii	"%d\012\000"
	.text
	.align	1
	.global	main
	.syntax unified
	.thumb
	.thumb_func
	.fpu vfpv3-d16
	.type	main, %function
main:
	@ args = 0, pretend = 0, frame = 24
	@ frame_needed = 1, uses_anonymous_args = 0
	push	{r7, lr} @ 将r7寄存器和lr寄存器值压入栈中,SP=SP-8
	sub	sp, sp, #48 @ 在栈上分配48字节空间
	add	r7, sp, #24 @ r7=SP+24
	str	r0, [r7, #4] @ 将r0寄存器中值存储到以r7为基址,偏移量为4的内存地址中
	str	r1, [r7] @ 将r1寄存器中值存储到以r7为基址的内存地址中
	movs	r3, #4 @ 将立即数4传送到r3寄存器
	str	r3, [r7, #20]
	movs	r3, #6
	str	r3, [r7, #16]
	movs	r3, #10
	str	r3, [r7, #12]
	add	r2, r7, #20 @ 将局部变量4的地址存储到r2寄存器
	add	r3, r7, #12 @ 将局部变量10的地址存储到r3寄存器
	str	r3, [sp, #20] @ 将r3寄存器中值存储到堆栈指针SP偏移为20的内存地址中
	movs	r3, #9
	str	r3, [sp, #16]
	movs	r3, #8
	str	r3, [sp, #12]
	movs	r3, #7
	str	r3, [sp, #8]
	add	r3, r7, #16
	str	r3, [sp, #4] @ 将局部变量6的地址存储到[SP,#4]
	movs	r3, #5
	str	r3, [sp]
	mov	r3, r2 @ r3=&e,r3存储局部变量e=4的地址
	movs	r2, #3 @ r2=3
	movs	r1, #2 @ r1=2
	movs	r0, #1 @ r0=1
	bl	func
	mov	r3, r0
	mov	r1, r3
	movw	r0, #:lower16:.LC0
	movt	r0, #:upper16:.LC0
	bl	printf
	movs	r3, #0
	mov	r0, r3
	adds	r7, r7, #24
	mov	sp, r7
	@ sp needed
	pop	{r7, pc}
	.size	main, .-main
	.ident	"GCC: (Linaro GCC 7.4-2019.02) 7.4.1 20181213 [linaro-7.4-2019.02 revision 56ec6f6b99cc167ff0c2f8e1a2eed33b1edc85d4]"
	.section	.note.GNU-stack,"",%progbits

在这里插入图片描述

ARM64 架构

@ aarch64-linux-gnu-gcc -S main.c -o main64.s

	.arch armv8-a
	.file	"main.c"
	.text
	.align	2
	.global	func
	.type	func, %function
func:
	sub	sp, sp, #48
	str	w0, [sp, 44]
	str	w1, [sp, 40]
	str	w2, [sp, 36]
	str	x3, [sp, 24]
	str	w4, [sp, 32]
	str	x5, [sp, 16]
	str	w6, [sp, 12]
	str	w7, [sp, 8]
	ldr	w1, [sp, 44] @ 从栈指针偏移44地址处加载32位值到w1寄存器
	ldr	w0, [sp, 40]
	add	w1, w1, w0
	ldr	w0, [sp, 36]
	add	w1, w1, w0
	ldr	x0, [sp, 24]
	ldr	w0, [x0]
	add	w1, w1, w0
	ldr	w0, [sp, 32]
	add	w1, w1, w0
	ldr	x0, [sp, 16]
	ldr	w0, [x0]
	add	w1, w1, w0
	ldr	w0, [sp, 12]
	add	w1, w1, w0
	ldr	w0, [sp, 8]
	add	w1, w1, w0
	ldr	w0, [sp, 48]
	add	w1, w1, w0
	ldr	x0, [sp, 56]
	ldr	w0, [x0]
	add	w0, w1, w0
	add	sp, sp, 48
	ret
	.size	func, .-func
	.section	.rodata
	.align	3
.LC0:
	.string	"%d\n"
	.text
	.align	2
	.global	main
	.type	main, %function
main:
	sub	sp, sp, #64
	stp	x29, x30, [sp, 16] @ 将x29,x30寄存器值从栈指针偏移16地址处开始压入 x29:SP+16,x30:SP+24
	add	x29, sp, 16 @ [SP,16]地址存储到x29
	str	w0, [x29, 28] @ w0值存储到[SP,44]地址处
	str	x1, [x29, 16] @ x1值存储到[SP,32]地址处
	mov	w0, 4
	str	w0, [x29, 44] @ [SP,60]=4
	mov	w0, 6
	str	w0, [x29, 40] @ [SP,56]=6
	mov	w0, 10
	str	w0, [x29, 36] @ [SP,52]=10
	add	x2, x29, 40 @ x2存储地址[SP,56]
	add	x1, x29, 44 @ x1存储地址[SP,60]
	add	x0, x29, 36 @ x0存储地址[SP,52]
	str	x0, [sp, 8] @ [SP,8]存储x0值,即[SP,8]=[SP,52]
	mov	w0, 9
	str	w0, [sp]
	mov	w7, 8 @ w7=8
	mov	w6, 7 @ w6=7
	mov	x5, x2 @ x5存储地址[SP,56],即局部变量g=6地址
	mov	w4, 5 @ w4=5
	mov	x3, x1 @ x3存储地址[SP,60],即局部变量e=4地址
	mov	w2, 3 @ w2=3
	mov	w1, 2 @ w1=2
	mov	w0, 1 @ w0=1
	bl	func
	mov	w1, w0
	adrp	x0, .LC0
	add	x0, x0, :lo12:.LC0
	bl	printf
	mov	w0, 0
	ldp	x29, x30, [sp, 16]
	add	sp, sp, 64
	ret
	.size	main, .-main
	.ident	"GCC: (Linaro GCC 7.5-2019.12) 7.5.0"
	.section	.note.GNU-stack,"",@progbits

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值