第18部分- Linux ARM汇编 函数调用示例

本文提供了32位和64位ARM汇编语言中函数调用的详细示例,包括函数定义、参数传递、返回值处理及栈平衡等关键概念。通过具体代码,展示了如何在不同架构下进行函数调用。

第18部分- Linux ARM汇编 函数调用示例

我们先来看个函数调用的示例。

 32位

定义函数如下,位于文件中:

.data
.balign 4
return2: .word 0

.text
.type mult_by_5,function
.globl mult_by_5
mult_by_5: 
    ldr r1, address_of_return2       /* r1 ← &address_of_return */
    str lr, [r1]                     /* *r1 ← lr */
 
    add r0, r0, r0, LSL #2           /* r0 ← r0 + 4*r0 */
 
    ldr lr, address_of_return2       /* lr ← &address_of_return */
    ldr lr, [lr]                     /* lr ← *lr */
    bx lr                            /* return from main using lr */
.balign 4
address_of_return2 : .word return2

进行函数文件汇编如下:

as -g -o mult_by_5.o mult_by_5.s

调用函数文件如下:

.data
 
.balign 4
message1: .asciz "Hey, type a number: "
.balign 4
message2: .asciz "%d times 5 is %d\n"
/* Format pattern for scanf */
.balign 4
scan_pattern : .asciz "%d"
/* Where scanf will store the number read */
.balign 4
number_read: .word 0
.balign 4
return: .word 0
.balign 4
return2: .word 0
 
.text
.global main
main:
    ldr r1, address_of_return        /* r1 ← &address_of_return */
    str lr, [r1]                     /* *r1 ← lr */
 
    ldr r0, address_of_message1      /* r0 ← &message1 */
    bl printf                        /* call to printf */
 
    ldr r0, address_of_scan_pattern  /* r0 ← &scan_pattern */
    ldr r1, address_of_number_read   /* r1 ← &number_read */
    bl scanf                         /* call to scanf */
 
    ldr r0, address_of_number_read   /* r0 ← &number_read */
    ldr r0, [r0]                     /* r0 ← *r0 */
    bl mult_by_5
 
    mov r2, r0                       /* r2 ← r0 */
    ldr r1, address_of_number_read   /* r1 ← &number_read */
    ldr r1, [r1]                     /* r1 ← *r1 */
    ldr r0, address_of_message2      /* r0 ← &message2 */
    bl printf                        /* call to printf */
 
    ldr lr, address_of_return        /* lr ← &address_of_return */
    ldr lr, [lr]                     /* lr ← *lr */
    bx lr                            /* return from main using lr */
address_of_message1 : .word message1
address_of_message2 : .word message2
address_of_scan_pattern : .word scan_pattern
address_of_number_read : .word number_read
address_of_return : .word return
 
/* External */
.global printf
.global scanf

as -g -o printf.o printf.s

gcc -g -o printf printf.o mult_by_5.o

再来看个64位的

 64位

ARM和ARM64使用的是ATPCS(ARM-Thumb Procedure Call Standard/ARM-Thumb过程调用标准)(或者是AAPCS)的函数调用约定。

参数1~参数8 分别保存到 X0~X7 寄存器中 ,剩下的参数从右往左一次入栈,被调用者实现栈平衡,返回值存放在 X0 中。

Registers

Description

X0 – X7

arguments and return value

X8 – X18

temporary registers

X19 – X28

callee-saved registers

X29

frame pointer

X30

link register

SP

stack pointer

 

定义函数如下:

.balign 4

.text
.type mult_by_5,@function
.globl mult_by_5
mult_by_5: 
    add x0, x0, x0, LSL #2           /* r0 ← r0 + 4*r0 */
    ret

进行汇编如下:

as -g -o mult_by_5.o mult_by_5.s

调用函数如下:

.data
.balign 4
message1: .asciz "Hey, type a number: "
 .balign 4
message2: .asciz "%d times 5 is %d\n"
/* Format pattern for scanf */
.balign 4
scan_pattern : .asciz "%d"
 
/* Where scanf will store the number read */
.balign 4
number_read: .word 0
 
.balign 4
return: .word 0
 
.balign 4
return2: .word 0
 
.text
.global _start
_start:
    ldr x0, address_of_message1      /* r0 ← &message1 */
    bl printf                        /* call to printf */
 
    ldr x0, address_of_scan_pattern  /* r0 ← &scan_pattern */
    ldr x1, address_of_number_read   /* r1 ← &number_read */
    bl scanf                         /* call to scanf */
 
    ldr x0, address_of_number_read   /* r0 ← &number_read */
    ldr x0, [x0]                     /* r0 ← *r0 */
    bl mult_by_5
 
    mov x2, x0                       /* r2 ← r0 */
    ldr x1, address_of_number_read   /* r1 ← &number_read */
    ldr x1, [x1]                     /* r1 ← *r1 */
    ldr x0, address_of_message2      /* r0 ← &message2 */
    bl printf                        /* call to printf */
      mov x8, 93
	svc 0

address_of_message1 : .dword message1
address_of_message2 : .dword message2
address_of_scan_pattern : .dword scan_pattern
address_of_number_read : .dword number_read
address_of_return : .dword return
 
/* External */
.global printf
.global scanf

as -g -o print64-f.o print64-f.s

ld -g -o print64-f print64-f.o mult_by_5.o -lc -I /lib64/ld-linux-aarch64.so.1

完成,可以运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值