微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 混合使用C、C++和汇编语之:内联汇编和嵌入型汇编的使用

混合使用C、C++和汇编语之:内联汇编和嵌入型汇编的使用

时间:08-30 来源:3721RD 点击:

4 sum, int a, int b)

{

#if !defined(__thumb) && defined(__TARGET_FEATURE_MULTIPLY)

__asm

{

SMLAL lo64(sum), hi64(sum), a, b

}

#else

sum += (__int64) a * (__int64) b;

#endif

return sum;

}

__int64 dotprod(int *a, int *b, unsigned n)

{

__int64 sum = 0;

do

sum = mlal(sum, *a++, *b++);

while (--n != 0);

return sum;

}

int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

int b[10] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };

int main(void)

{

printf("Dotproduct %lld (should be %d)\n", dotprod(a, b, 10), 220);

return 0;

}

2.内联汇编中的限制

可以在内联汇编代码中执行的操作有许多限制。这些限制提供安全的方法,并确保在汇编代码中不违反 C 和 C++ 代码编译中的假设。

① 不能直接向程序计数器PC赋值。

② 内联汇编不支持标号变量。

③ 不能在程序中使用"."或{PC}得到当前指令地址值。

④ 在16进制常量前加"0x"代替"&"。

⑤ 建议不要对堆栈进行操作。

⑥ 编译器可能会使用r12和r13寄存器存放编译的中间结果,在计算表达式值时可能会将寄存器r0~r3、r12及r14用于子程序调用。另外在内联汇编中设置程序状态寄存器CPSR中的标志位NZCV时,要特别小心,内联汇编中的设置很可能会和编译器计算的表达式的结果冲突。

⑦ 用内联汇编代码更改处理器模式是可能的。然而,更改处理器模式会禁止使用 C或 C++操作数或禁止对已编译C或C++代码的调用,直到将处理器模式更改回原设置之后之前的函数库才可正常使用。

⑧ 为Thumb状态编译C或C++时,内联汇编程序不可用且不汇编Thumb指令。

⑨ 尽管可以使用通用协处理器指令指定 VFP 或 FPA 指令,但内联汇编程序不为它们提供直接支持。

不能用内联汇编代码更改 VFP 向量模式。内联汇编可包含浮点表达式操作数,该操作数可使用编译程序生成的 VFP 代码求出操作数值。因此,仅由编译程序修改 VFP 状态很重要。

⑩ 内嵌汇编不支持的指令有BX、BLX、BXJ和BKPT指令。而LDM、STM、LDRD和STRD指令可能被等效为ARM LDR或STR指令。

3.内联汇编中的虚拟寄存器

内联汇编程序提供对 ARM 处理器物理寄存器的非直接访问。如果在内联汇编程序指令中将某个ARM寄存器用作操作数,它就成为相同名称的虚拟寄存器的引用,而不是对实际物理ARM寄存器的引用。例如内联汇编指令中使用了寄存器r0,但对于C编译器,指令中出现的r0只是一个变量,并非实际的物理寄存器r0,当程序运行时,可能是由物理寄存器r1来存放r0所代表的值。

下面的例子显示了编译器如何对内联汇编指令的寄存器进行分配。

程序的源代码如下。

#include <stdio.h>

void test_inline_register(void)

{

int i;

int r5,r6,r7;

__asm

{

MOV i,#0

loop:

MOV r5,#0

MOV r6,#0

MOV r7,#0

ADD i,i,#1

CMP i,#3

BNE loop

}

}

int main(void)

{

test_inline_register ();

printf("test inline register\n");

return 0;

}

由C编译器编译出的汇编码如下所示。

test_inline_register:

0000807C E3A00000 MOV r0,#0

>>> TEST_INLINE_REGISTER\#12 loop:

00008080 E1A00000 NOP

>>> TEST_INLINE_REGISTER\#13 MOV r5,#0

00008084 E3A01000 MOV r1,#0

>>> TEST_INLINE_REGISTER\#14 MOV r6,#0

00008088 E3A02000 MOV r2,#0

>>> TEST_INLINE_REGISTER\#15 MOV r7,#0

0000808C E3A03000 MOV r3,#0

>>> TEST_INLINE_REGISTER\#16 ADD i,i,#1

00008090 E2800001 ADD r0,r0,#1

>>> TEST_INLINE_REGISTER\#17 CMP i,#3

00008094 E3500003 CMP r0,#3

00008098 0A000000 BEQ 0x80a0 <TEST_INLINE_REGISTER\#21>

>>> TEST_INLINE_REGISTER\#18 BNE loop

0000809C EAFFFFF8 B 0x8084 <TEST_INLINE_REGISTER\#13>

>>> TEST_INLINE_REGISTER\#21 }

000080A0 E12FFF1E BX r14

>>> TEST_INLINE_REGISTER\#25 {

注意

下面的代码是由Realview2.2编译出的代码,使用其他编译器结果可能有差异。同一段内嵌汇编

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

网站地图

Top