文章目录
-
为了实现C和汇编的相互调用,有一个ATPCS规则(ARM公司制定的),是以下三点内容:
- 程序中统一使用满减栈, 该栈是8字节对齐
- 传递参数时,前4个参数使用r0 r1 r2 r3来传递,剩余参数使用栈来传递
- 函数的返回值使用r0
汇编调用C
c
/*add.c*/
int my_add(int x, int y, int z, int m, int n){
return x + y + z + m + n;
}
- 汇编中如能调用my_add函数分为四步:
- 步骤一: 使用.extern 在汇编文件中声明my_add是外部符号
- 步骤二:调用前准备好传递给my_add的参数到 r0、 r1寄存器(遵循ATPCS规则)
- 步骤三:通过bl my_add 完成调用
- 步骤四:调用结束后,直接读取r0获取返回值 (遵循ATPCS规则)
z80
.text
.global _start @将_start声明为全局的
.extern my_add
_start:
@先初始化要使用的栈空间
ldr sp, =0x400
mov r0, #10
mov r1, #20
mov r2, #30
mov r3, #40
mov r8, #50
push {r8}
bl my_add
b .
.data
.align 4 @按2^4字节对齐
.space 4096
.end
C调用汇编
- C中调用汇编中实现的my_add函数分为三步:
- 步骤一:定义汇编函数my_add, 注意传递的参数、返回值满足ATCPS规则
- 步骤二:汇编文件中通过.global 把my_add声明为全局的
- 步骤三:C语言中通过extern声明外部函数my_add
z80
/*add.s*/
.arm
.text
.global my_add
my_add:
add r0, r0, r1
add r0, r1, r2
mov pc, lr
.end
c
/*main.c*/
extern int my_add(int, int, int);
int main(void){
int ret = my_add(1,2,3);
return ret;
}
z80
/* start.s */
text
.global _start
.extern main
_start:
ldr sp, =0x400
mov r0, #100
b main
.data
.align 4
.space 4096
.end

C中嵌套汇编

z80
asm volatile (
"汇编指令\n\t"
....
:输出列表
:输入列表
:破坏列表
);
- asm: 编译器将不检查后面的内容,而是直接交给汇编器处理
- volatile, 向GCC声明不允许对该内联汇编进行优化
c
/*r 表示通用寄存器*/
int func(int a, int b){
int c = 0;
asm volatile(
"add %0, %1, %2"
:"=r"(c)
:"r"(a),"r"(b)
:"memory"
);
return c;
}
c
/*cc, 表示cpsr*/
int enable_irq(){
int status;
asm volatile(
"mrs r0, cpsr\n\t"
"bic r0, r0, #(1<<7)\n\t"
"msr cpsr_c, r0\n\t"
"mrs %0, cpsr\n\t"
:"=r"(status)
:
:"r0", "cc", "memory"
);
return status&(1<<7)? 1:0 ;
}