第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
完成,可以运行。