ATPCS 规则
ATPCS : ARM-Thumb Procedure Call Standard
堆栈使用规则
使用满递减堆栈(FD),入栈出栈操作使用 LDMFD/STMFD
子程序调用基本规则
- 子程序间通过寄存器R0~R3传递参数和返回结果,参数多于4个,其余的使用堆栈传参。
- 子程序使用R4~R11保存局部变量。
- R12作为过程调用中的临时寄存器,用于保存SP。
- R13作为数据栈指针。
- R14作为连接寄存器,保存子程序的返回地址。
- R15作为程序计数器。
ARM编译器内嵌汇编
__asm
ARM编译器对ANSI C进行扩展,使用__asm在C中内嵌汇编
int src[10] = {1,2,3,4,5,6,7,8,9,0};
int dst[10] = {0};
int i = 0;
int main(void)
{
for (i=0; i<10; i++)
dst[i] = src[i];
return 0;
}
int src[10] = {1,2,3,4,5,6,7,8,9,0}
int dst[10] = {0};
int i = 0;
int main(void) {
__asm
{
ldr r0, =src
ldr r1, =dst
mov r2, #10
loop:
ldr r3, [r0], #4
str r3, [r1], #4
subs r2, r2, #1
bne loop
}
return 0;
}
GNU 内嵌汇编
__asm__
GCC 编译器对ANSI C扩展,使用__asm__修饰,表示后面的代码为内嵌汇编,其后可选择使用__volatile__告诉编译器不要优化代码。
#include <stdio.h>
int src[10] = {1,2,3,4,5,6,7,8,9,0};
int dst[10] = {0};
int main(void) {
int i = 0;
__asm__ __volatile__
(
"ldr r0, =src;"
"ldr r1, =dst;"
"mov r2, #10;"
"loop:"
"ldr r3, [r0], #4;"
"str r3, [r1], #4;"
"subs r2, r2, #1;"
"bne loop;"
);
for (i=0;i<10;i++)
printf("dst[%d] = %d\n", i, dst[i]);
return 0;
}
汇编中调用C子程序
根据ATPCS参数规则,完成参数传递
满足C语言参数传递和局部变量保存的堆栈环境
使用 BL func
伪代码
IMPORT sum;
AREA SUM_ASM, CODE, READONLY
EXPORT SUM_ASM
SUM_ASM
MOV R0,0x3 ; 参数保存到r0
MOV R1,0x4 ; 参数保存到r1
BL sum
MOV PC,LR
END
int sum(int a, int b)
{
int result = 0;
printf("result=%d\n",result);
return result;
}
int main(void)
{
SUM_ASM();
return 0;
}
IMPORT sum;
AREA SUM_ASM, CODE, READONLY
EXPORT SUM_ASM
SUM_ASM
MOV R0,0x0
MOV R1,0x1
MOV R2,0x2
MOV R3,0x3
MOV R4,0x5
STR r4,[SP, #-4]
MOV R4, 0x4
STR r4,[SP, #-4]
BL sum
MOV PC,LR
END
int sum(int a, int b, int c, int d, int e, int f)
{
int result = a+b+c+d+e+f;
printf("result=%d\n",result);
return result;
}
int main(void)
{
SUM_ASM();
return 0;
}