微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM之---在C语言中内嵌汇编语言

ARM之---在C语言中内嵌汇编语言

时间:11-11 来源:互联网 点击:
开发Arm程序的时候,大多数时候使用C/C++语言就可以了,但汇编语言在某些情况下能够实现一些C语言无法实现的功能,这时候就要调用一些汇编语言的程序.我们需要大概了解一下在C语言中如何嵌入汇编语言.

1.内嵌汇编语言的语法:

__asm

{

指令[;指令]

......

[指令]

}

2.举例:使能/禁止IRQ中断

__inline void enable_IRQ(void)

{

int tmp;

__asm//嵌入汇编代码

{

MRStmp,CPSR//读取CPSR的值

BICtmp,tmp,#0x80//将IRQ中断禁止位I清零,即允许IRQ中断

MSRCPSR_c,tmp//设置CPSR的值

}

}

__inline void disable_IRQ(void)

{

int tmp;

__asm

{

MRStmp,CPSR

ORRtmp,tmp,#Ox80

MSRCPSR_c,tmp

}

}

3.举例:字符串复制

void my-strcpy(const char *src,char *dst)

{

int ch;

__asm

{

loop:

#ifndef __thumb

LDRB ch,[src],#1

STRB ch,[dst],#1

#else

LDRB ch,[src]

ADDsrc,#1

STRB ch,[dst]

ADDdst,#1

#endif

CMP ch,#0

BNE loop

}

}

int main(void)

{

const char *a="Hello world!";

char b[20];

__asm

{

MOVR0,a

MOVR1,b

BL my_strcpy,{R0,R1}

}

return(0);

}

4.内嵌汇编的指令用法:

.操作书: 内嵌的汇编指令中作为操作数的寄存器和常量可以是C表达式.这些表达式可以是char,short或int等类型,而且这些表达式都是作为无符号数进行操作的.若要有符号数,用户需要自己处理与符号有关的操作.编译器将会计算这些表达式的值,并为其分配寄存器.

.物理寄存器:内嵌汇编中使用物理寄存器是有限制的:

_ 不能直接向PC(程序计数器)寄存器中赋值,程序跳转只能通过B或BL指令来实现.

_ 使用物理寄存器的指令中,不要使用过于复杂的C表达式

_ 尽可能少的使用物理寄存器

.常量: 在内嵌汇编指令中,常量前面的"#"可以省略

.标号: C程序中的标号可以被内嵌的汇编指令使用.但是只有指令B可以使用C程序中的标号,而指令BL则不能使用.

.内存单元的分配:所有内存分配均由C编译器完成,分配的内存单元通过变量供内嵌汇编器使用.内嵌汇编器不支持内嵌汇编程序中用于内存分配的伪指令.

5.内嵌汇编注意事项:

.必须小心使用物理寄存器,如R0~R3,IP,LR,CPSR中的标志位,避免发生冲突.

例如:

__asm

{

MOVR0,x

ADDy,R0,x/y

}

改成下面代码会比较妥当:

__asm

{

MOV var,x

ADD y,var,x/y

}

.不要使用寄存器代替变量.

.使用内嵌汇编无需保存和恢复寄存器.事实上,除了CPSR,SPSR寄存器,对物理寄存器先读后写都会引起汇编报错.

.汇编语言中","号作为操作数分隔符.如果有C表达式作为操作数,若表达式中包含有",",则必须使用()将其规约为一个汇编操作数,例如:

__asm
{

ADD x,y,(f(),z)//"f(),z"为带有","的C表达式.

}

6.不同数据类型对应的汇编指令:

unsigned charLDRB/STRB

unsigned shortLDRH/STRH

unsigned int LDR/STR

char LDRSB/STRSB

short LDRSH/STRSH

7.访问C程序的变量:

AREAglobals,CODE,READONLY

EXPORTasmsubroutine

IMPORTglobalvar;声明的外部变量

asmsubroutine

LDRR1,=blobalval

LDRR0,[R1]

ADDR0,R0,#1

STRR0,[R1]

MOVPC,LR

END

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top