参考链接
函数调用参数传递
对于 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