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

时间:2013-09-30来源:网络

例子中以“>>>”的开头的行是程序的源码部分,紧接其后的是由编译器编译出的汇编代码。从上例可以很清楚地看出,源程序中使用了r5、r6和r7,但由编译器编译后的代码使用了寄存器r1、r2和r3。

另外,需要特别指出的是在内联汇编中使用寄存器必须先声明其变量类型,如上例中的“intr5,r6,r7”。如果不在使用前进行声明,编译器将给出以下错误信息。

#1267-D:ImplicitphysicalregisterR3shouldbedefinedasavariable

编译程序定义的虚拟寄存器有函数局部作用范围,即在同一个C函数中,涉及相同虚拟寄存器名称的多个asm语句或声明,访问相同的虚拟寄存器。

内联汇编没有为pc(r15)、lr(r14)和sp(r13)寄存器创建虚拟寄存器,而且不能在内联汇编代码中读取或直接修改它们的值。如果内联汇编程序中出现了对这些寄存器的访问,编译器将给出以下错误消息。例如,如果指定r14:

#20:identifierr14isundefined

内联汇编可以直接使用CPSR和SPSR对程序状态字进行操作,因为内联汇编中不存在虚拟处理器状态寄存器(PSR)。任何对PSR的引用总是指向物理PSR。

4.内联汇编中的指令展开

内联汇编代码中的ARM指令可能会在编译过程中扩展为几条指令。扩展取决于指令、指令中指定的操作数个数以及每个操作数的类型和值。通常,被扩展的指令有以下两种情况:

·含有常数操作的指令;

·LDM、STM、LDRD和STRD指令;

·乘法指令MUL被扩展为一系列的加法和移位指令。

下面的例子说明了编译器如何对含有常数操作的指令进行扩展。

包含有常数操作的加法指令:

ADDr0,r0,#1023

被编译器编译为如下两条指令:

ADDr0,r0,#1024

SUBr0,r0,#1

注意

扩展指令对程序状态寄存器CPSR的影响:算术指令影响相应的NZCV标准位;其他指令设置NZ标志位不影响V标志位。

所有的LDM和STM指令被扩展为等效的LDR和STR指令序列。然而,在优化过程中,编译程序可能因此将单独的指令重组为一条LDM或STM指令。

5.内联汇编中的常数

指令中的标志符“#”是可选的(前面的例子中,指令中常数前均加了标志符“#”)。如果在指令中使用了“#”,则其后的表达式必为常数。

6.内联汇编指令对标志位的影响

内联汇编指令可能显式或隐式地更新处理器程序状态寄存器的条件标志位。在仅包含虚拟寄存器操作数或简单表达式操作数的内联汇编中,其执行结果是可以预见。如果指令中指定了隐式或显式更新条件标志位,则条件标志位根据指令的执行进行设置。如果未指定更新,则条件标志不会更改。如果内嵌汇编指令的操作数都不是简单操作数时或指令不显式更新条件标志位,则条件标志位可能会被破坏。一般情况下,编译程序不易诊断出对条件标志的潜在破坏。然而,在构造析构C++临时函数的操作数时,如果指令试图更新条件标志,编译程序将给予警告,因为析构函数可能会破坏条件标志位。

1 2 3 4 5 6 7 8 9 10 11

关键词: C C++ 汇编语言 内联汇编 嵌入型汇编 ARM

加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW

或用微信扫描左侧二维码

相关文章

查看电脑版