首页 理论教育 内嵌汇编的应用及注意事项

内嵌汇编的应用及注意事项

时间:2023-11-23 理论教育 版权反馈
【摘要】:⑤通常在内嵌的汇编指令中不要指定物理寄存器,因为这可能会影响编译器分配寄存器,进而可能影响代码的效率。4)标号C 语言程序中的标号可以被内嵌的汇编指令使用,但是只有指令B 可以使用C 语言程序中的标号,指令BL 不能使用C 语言程序中的标号。2)使能和禁止中断本例主要介绍如何利用内嵌汇编程序来使能和禁止中断。

内嵌汇编的应用及注意事项

在C 语言程序中嵌入汇编程序,可以实现一些高级语言没有的功能,并可以提高执行效率。 armcc 和armcpp 内嵌汇编器支持完整的ARM 指令集;tcc 和tcpp 用于Thumb 指集。 但是,内嵌汇编器并不支持诸如直接修改PC 实现跳转的底层功能。

虽然内嵌的汇编指令包括大部分的ARM 指令和Thumb 指令,但是不能直接引用C 语言的变量定义,数据交换必须通过ATPCS 进行。 嵌入式汇编在形式上表现为独立定义的函数体。

(1)内嵌汇编指令的语法格式

__asm(“指令[;指令]”);

ARM C 汇编器使用关键字“__asm”。 如果有多条汇编指令需要嵌入,可以用“{}”将它们归为一条语句。 如:

各指令用“;”分隔。 如果一条指令占据多行,除最后一行外都要使用连字符“\”。 在汇编指令段中,可以使用C 语言的注释语句。 需要特别注意的是__asm 是两条下画线。

(2)内嵌的汇编指令的特点

1)操作数

在内嵌的汇编指令中,操作数可以是寄存器、常量或C 语言表达式。 它们可以是char、short 或者int 类型,而且都是作为无符号数进行操作。 如果需要有符号数,用户需要自己处理与符号有关的操作。 编译器将计算这些表达式的值,并为其分配寄存器。

当汇编指令中同时用到了物理寄存器和C 语言的表达式时,要注意使用的表达式不要过于复杂。

2)物理寄存器

在内嵌的汇编指令中使用物理寄存器有以下限制:

①不能直接向PC 寄存器中赋值,程序的跳转只能通过B 指令和BL 指令实现。

②在使用物理寄存器的内嵌汇编指令中,不要使用过于复杂的C 语言表达式。 因为当表达式过于复杂时,会需要较多的物理寄存器,这些寄存器可能与指令中的物理寄存器的使用冲突。 当编译器发现了寄存器的分配冲突时,会产生相应的错误信息,报告寄存器分配冲突。

③编译器可能会使用R12 寄存器或者R13 寄存器存放编译的中间结果,在计算表达式值时,可能会将寄存器R0 到R3、R12 以及R14 用于子程序调用。 因此,在内嵌的汇编指令中,不要将这些寄存器同时指定为指令中的物理寄存器。

④在内嵌的汇编指令中使用物理寄存器时,如果有C 语言变量使用了该物理寄存器,编译器将在合适时保存并恢复该变量的值。

⑤通常在内嵌的汇编指令中不要指定物理寄存器,因为这可能会影响编译器分配寄存器,进而可能影响代码的效率。

3)常量

在内嵌的汇编指令中,常量前的符号“#”可以省略。 如果在一个表达式中使用符号“#”,该表达式必须是一个常量。

4)标号

C 语言程序中的标号可以被内嵌的汇编指令使用,但是只有指令B 可以使用C 语言程序中的标号,指令BL 不能使用C 语言程序中的标号。 指令B 使用C 语言程序中的标号时,语法格式如下所示:

B{cond}label

5)内存单元的分配

内嵌汇编器不支持汇编语言中用于内存分配的伪操作。 所用的内存单元的分配都是通过C 语言程序完成的,分配的内存单元通过变量供内嵌的汇编器使用。

6)指令展开

内嵌的汇编指令中如果包含常量操作数,该指令可能会被汇编器展开成几条指令。例如,指令“ADD R0,R0,#1023”可能会被展开成下面的指令序列:

ADD R0,R0,#1024

SUB R0,R0,#01

乘法指令MUL 可能会被展开成一系列的加法操作和移位操作。 事实上,除了与协处理器相关的指令外,大部分的ARM 指令和Thumb 指令中包含常量操作数都可能被展开成多条指令。 各展开的指令对CPSR 寄存器中的各条件标志位有如下影响:(www.xing528.com)

①算术指令可以正确地设置CPSR 寄存器中的NZCV 条件标志位。

②逻辑指令可以正确地设置CPSR 寄存器中的NZ 条件标志位,不影响V 条件标志位,破坏C 语言条件标志位(使C 语言标志位变得不准确)。

7)SWI 和BL 指令的使用

在内嵌的SWI 和BL 指令中,除了正常的操作数域外,还必须增加以下三个可选的寄存器列表。

①第一个寄存器列表中的寄存器用于存放输入的参数。

②第二个寄存器列表中的寄存器用于存放返回的结果。

③第三个寄存器列表中的寄存器供被调用的子程序作为工作寄存器,这些寄存器的内容可能被调用的子程序破坏。

8)内嵌汇编器与armasm 汇编器的区别

内嵌汇编器与armasm 汇编器的区别如下:

①内嵌汇编器不支持通过“·”指示符或PC 获取当前指令地址

②不支持LDR Rn,= expression 伪指令,而使用MOV Rn, expression 指令向寄存器赋值。

③不支持标号表达式。

④不支持ADR 和ADRL 伪指令。

⑤不支持BX 和BLX 指令。

⑥不可以向PC 赋值。

⑦使用0x 前缀替代“&”表示十六进制数。 当使用8 位移位常量导致CPSR 中的ALU 标志位需要更新时,NZCV 标志中的C 不具有真实意义。

(3)内嵌汇编指令的应用举例

下面是在C 语言程序中嵌入汇编程序的例子。 通过以下例子,可以帮助用户更好地理解内嵌汇编的特点及用法。

1)字符串复制

本例主要介绍如何使用指令BL 调用子程序。

注意,由内嵌汇编的特点可知,在内嵌的SWI 和BL 指令中,除了正常的操作数域外,还必须增加下面三个可选的寄存器列表。 在这个程序里就能体现这一点。

示例:使用指令BL 调用子程序。

在这个例子中,主函数main()中的BL my_strcpy,{R0,R1}指令的输入寄存器列表为{R0,R1},没有输出寄存器列表。 子程序使用的工作寄存器为ATPCS 默认工作寄存器R0 ~R3、R12、lr 以及PSR。

2)使能和禁止中断

本例主要介绍如何利用内嵌汇编程序来使能和禁止中断。

使能和禁止中断是通过修改CPSR 寄存器中的[位7]完成的。 这些操作必须在特权模式下进行,因为在用户模式下不能修改CPSR 寄存器中的控制位。

示例:中断的使能和禁止。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈