混合使用C、C++和汇编语之:内联汇编和嵌入型汇编的使用
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编译出的代码,使用其他编译器结果可能有差异。同一段内嵌汇编 |
C C++ 汇编语言 ARM 内联汇编 嵌入型汇编 相关文章:
- RedHatLinux新手入门教程(5)(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- VXWORKS内核分析(11-11)
- 嵌入式开发工具简介(11-09)
- Linux2.4内核为我们带来了什么?(11-12)
- RedHatLinux新手入门教程(11-12)