ARM汇编语言程序设计
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
} return x; }
Chavezwang@gmail.com
// 不需要恢复寄存器.
}
EOR x, r0, x
return x; }
计算机学院嵌入式实验室 13
北京理工大学珠海学院
嵌入式系统设计及应用开发
内联汇编语法
① __asm("instruction[;instruction]"); // 必须为单条指令 __asm{instruction[;instruction]} ② __asm{ ... instruction ... } ③ asm("instruction[;instruction]"); // 必须为单条指令 asm{instruction[;instruction]} ④ asm{ ... instruction ... }
9
Chavezwang@gmail.com
计算机学院嵌入式实验室
北京理工大学珠海学院
嵌入式系统设计及应用开发
相互调用必须遵循AAPCS
Register
作为函数传递的参数值
r0 r1 r2 r3 r4 r5 r6 r7 r8 r9/sb r10/sl r11
r12 r13/sp r14/lr r15/pc
可能被变形为等效的ARM LDR或STR指令
Chavezwang@gmail.com 计算机学院嵌入式实验室 18
北京理工大学珠海学院
嵌入式系统设计及应用开发
内联汇编中的虚拟寄存器
内联汇编程序提供对 ARM 处理器物理寄存器的非直接访 问。如果在内联汇编程序指令中将某个 ARM 寄存器用作 操作数,它就成为相同名称的虚拟寄存器的引用,而不是 对实际物理 ARM 寄存器的引用。例如内联汇编指令中使 用了寄存器r0,但对于C编译器,指令中出现的r0只是一 个变量,并非实际的物理寄存器r0,当程序运行时,可能
编译器使用一套规则的来设置寄存器的用法
CPSR 标志位可被函数调用所破坏 一些和编译过的代码交互工作的汇编码在接口层必 须满足的规范
寄存器变量 必须保护
- 如果 RWPI选项有效,作为栈的基地址 - 如果软件堆栈检查有效,作为栈的限制值
Scratch register (corruptible)
Stack Pointer Link Register Program Counter
北京理工大学珠海学院
嵌入式系统设计及应用开发
内联汇编的限制3
持。
⑨ 尽管可以使用通用协处理器指令指定 VFP 或 FPA 指令,但内联汇编程序不为它们提供直接支
不能用内联汇编代码更改 VFP 向量模式。内联汇
编可包含浮点表达式操作数,该操作数可使用编译
程序生成的 VFP 代码求出操作数值。因此,仅由 编译程序修改 VFP 状态很重要。 ⑩ 内嵌汇编不支持的指令:BX、BLX、BXJ和 BKPT指令。而LDM、STM、LDRD和STRD指令
Chavezwang@gmail.com
计算机学院嵌入式实验室
5
北京理工大学珠海学院
嵌入式系统设计及应用开发
注意
源文件中段之间的相对位置与可执行的映 像文件中段的相对位置可能不相同
ZI RO-DATA RW RO-CODE CODE B
A
RO
Chavezwang@gmail.com
计算机学院嵌入式实验室
END
这里所有的参数都是可以用寄存器来传递的,所以不需要在汇编程序中使用 PUSH/POP来保护
计算机学院嵌入式实验室 11
Chavezwang@gmail.com
北京理工大学珠海学院
内联汇编的特点1
嵌入式系统设计及应用开发
Leabharlann Baidu
由于内联汇编嵌入在C或C++程序中,所有在用法上有其自身的一些特点。 ① 如果同一行中包含多条指令,则用分号隔开。
③ 不能在程序中使用“.”或{PC}得到当前指令地址值。
④ 在16进制常量前加“0x”。
⑤ 建议不要对堆栈进行操作。
Chavezwang@gmail.com
计算机学院嵌入式实验室
16
北京理工大学珠海学院
嵌入式系统设计及应用开发
内联汇编的限制2
⑥ 编译器可能会使用r12和r13寄存器存放编译的中间结果, 在计算表达式值可能会将寄存器r0~r3、r12及r14用于子程 序调用。另外在内联汇编中设置程序状态寄存器CPSR中的 标志位NZCV时,要特别小心。内联汇编中的设置很可能会 和编译器计算的表达式的结果冲突。
extern void mystrcopy(char *d, const char *s); int main(void) { const char *src = “Source”; char dest[10]; CALL ... mystrcopy(dest, src); ... }
mystrcopy LDRB r2, [r1], #1 STRB r2, [r0], #1 CMP r2, #0 BNE mystrcopy MOV pc, lr
Chavezwang@gmail.com 计算机学院嵌入式实验室 14
北京理工大学珠海学院
嵌入式系统设计及应用开发
内联汇编( Inline assembler
使用C变量代替寄存器
/* Q flag is bit 27 of PSR */ const int Q_Flag=0x08000000; __inline int Clear_Q_flag (void) { int old_psr, new_psr, result;
- r14值压栈以后,r14可作为一个临时寄存器使用
Chavezwang@gmail.com
计算机学院嵌入式实验室
10
北京理工大学珠海学院
嵌入式系统设计及应用开发
在C程序中调用汇编
在汇编程序中用export name来定 义 在C程序中直接调用 一般的链接即可
AREA StringCopy, CODE, READON EXPORT mystrcopy
合内联汇编的语法规 则。 int f(int x) { STMFD sp!, {r0} ADD r0, x, 1 EOR x, r0, x // 保存r0 – 不合法,因 int r0; __asm { 为在读之前没有对寄存器寄存器写操作
{
__asm
{ ADD r0, x, 1
LDMFD sp!, {r0}
Chavezwang@gmail.com 计算机学院嵌入式实验室 20
{
test_inline_register (); printf("test inline register\n");
return 0; }
北京理工大学珠海学院
嵌入式系统设计及应用开发
test_inline_register: 输出结果
⑥ 内联汇编中的寄存器(除程序状态寄存器CPSR和SPSR外)在读取前必 须先赋值,否则编译器将产生错误信息。
Chavezwang@gmail.com
计算机学院嵌入式实验室
12
北京理工大学珠海学院
嵌入式系统设计及应用开发
错误的内联汇编函数如下所示。 int f(int x)
内联汇编与汇编之间的区别 将其进行改写,是它符
IAR汇编器支持的伪指令 简单汇编语言程序设计
Chavezwang@gmail.com
计算机学院嵌入式实验室
3
北京理工大学珠海学院
嵌入式系统设计及应用开发
汇编语言程序设计规范-段
段:相对独立的指令或数据序列,具有特点的名 称 段:
– –
代码段:内容为执行代码 数据段:存放代码代码运行时需要用到 的数据
⑦ 可以使用内联汇编代码更改处理器模式。然而,更改处理
器模式会禁止使用 C或 C++ 操作数或对已编译 C 或 C++ 代码的调用,直到将处理器模式更改回原设置之后之前的函
数库才可正常使用。
⑧ 为 Thumb 状态编译 C 或 C++ 时,内联汇编程序不可用且 不汇编 Thumb 指令。
Chavezwang@gmail.com 计算机学院嵌入式实验室 17
6
混合使用C/C++/汇编
北京理工大学珠海学院
嵌入式系统设计及应用开发
混合使用C/C++/汇编
内联汇编和嵌入型汇编的使用 从汇编代码访问 C 全局变量 在C++中使用C头文件 C、C++ 和 ARM 汇编语言之间的调用
Chavezwang@gmail.com
计算机学院嵌入式实验室
8
计算机学院嵌入式实验室 15
Chavezwang@gmail.com
北京理工大学珠海学院
嵌入式系统设计及应用开发
内联汇编的限制1
可以在内联汇编代码中执行的操作有许多限制。这些限 C++ 代码编译中的规则。 ① 不能直接向程序计数器PC赋值。 ② 内联汇编不支持标号变量。
制提供安全的方法,并确保在汇编代码中不违反 C 和
是由物理寄存器r1来存放r0所代表的值。
Chavezwang@gmail.com
计算机学院嵌入式实验室
19
北京理工大学珠海学院
嵌入式系统设计及应用开发
内联汇编中虚拟寄存器举例
int main(void) #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 } }
多个段在程序编译链接时最终形成一个可执行的 代码段
计算机学院嵌入式实验室 4
Chavezwang@gmail.com
北京理工大学珠海学院
嵌入式系统设计及应用开发
段的设置规则
一个或多个代码段,代码段的属性为只读 0个或多个包含初始化数据的数据段,数据 段的属性为可读/写 0个或多个不包含初始化数据的数据段,数 据段的属性为可读/写
② 如果一条指令不能在一行中完成,使用反斜杠“/”将其连接。
③ 内联汇编中的注释语句可以使用C或C++风格的。 ④ 汇编语言中使用逗号“,”作为指令操作数的分隔符,所以如果在C语 言中使用逗号必须用圆括号括起来。如,__asm {ADD x, y, (f(), z)}。 ⑤ 内联汇编语言中的寄存器名被编译器视为C或C++语言中的变量,所以内 联汇编中出现的寄存器名不一定和同名的物理寄存器相对应。而且这些 寄存器名在使用前必须声明,否则编译器将提示警告信息。
0000807C E3A00000 MOV r0,#0 >>> TEST_INLINE_REGISTER\#12 loop: 00008080 E1A00000 NOP >>> TEST_INLINE_REGISTER\#13 MOV 00008084 E3A01000 MOV r1,#0 >>> TEST_INLINE_REGISTER\#14 MOV 00008088 E3A02000 MOV r2,#0 >>> TEST_INLINE_REGISTER\#15 MOV 0000808C E3A03000 MOV r3,#0 >>> TEST_INLINE_REGISTER\#16 ADD 00008090 E2800001 ADD r0,r0,#1 >>> TEST_INLINE_REGISTER\#17 CMP 00008094 E3500003 CMP r0,#3 00008098 0A000000 BEQ 0x80a0 <TEST_INLINE_REGISTER\#21> >>> TEST_INLINE_REGISTER\#18 BNE 0000809C EAFFFFF8 B 0x8084 <TEST_INLINE_REGISTER\#13> >>> TEST_INLINE_REGISTER\#21 } 计算机学院嵌入式实验室 Chavezwang@gmail.com 000080A0 E12FFF1E BX r14
不是一个真正的汇编文件
通过优化器实现 代码可能被改变
只支持在ARM 模式 (not Thumb) 可以有自己独立的函数,但通 常是内嵌在C函数中
__asm
{ MRS old_psr, CPSR BIC new_psr, old_psr, #Q_Flag AND result, old_psr, #Q_Flag MSR CPSR_f, new_psr } return result; }
北京理工大学珠海学院
嵌入式系统设计及应用开发
何时使用内联汇编和嵌入型汇编
程序中使用饱和算术运算(Saturating arithmetic),如SSAT16 和 USAT16指令。
程序中需要对协处理器进行操作。 在C或C++程序中完成对程序状态寄存器的操作
注:使用内联汇编编写的程序代码效率也比较高
ARM 汇编语言程序 设计
北京理工大学珠海学院
嵌入式系统设计及应用开发
特别说明
开发工具不同所以的 编译语言伪指令不同
– – –
GCC ADS IAR
Chavezwang@gmail.com
计算机学院嵌入式实验室
2
北京理工大学珠海学院
嵌入式系统设计及应用开发
汇编语言程序设计
汇编程序设计规范
Chavezwang@gmail.com
// 不需要恢复寄存器.
}
EOR x, r0, x
return x; }
计算机学院嵌入式实验室 13
北京理工大学珠海学院
嵌入式系统设计及应用开发
内联汇编语法
① __asm("instruction[;instruction]"); // 必须为单条指令 __asm{instruction[;instruction]} ② __asm{ ... instruction ... } ③ asm("instruction[;instruction]"); // 必须为单条指令 asm{instruction[;instruction]} ④ asm{ ... instruction ... }
9
Chavezwang@gmail.com
计算机学院嵌入式实验室
北京理工大学珠海学院
嵌入式系统设计及应用开发
相互调用必须遵循AAPCS
Register
作为函数传递的参数值
r0 r1 r2 r3 r4 r5 r6 r7 r8 r9/sb r10/sl r11
r12 r13/sp r14/lr r15/pc
可能被变形为等效的ARM LDR或STR指令
Chavezwang@gmail.com 计算机学院嵌入式实验室 18
北京理工大学珠海学院
嵌入式系统设计及应用开发
内联汇编中的虚拟寄存器
内联汇编程序提供对 ARM 处理器物理寄存器的非直接访 问。如果在内联汇编程序指令中将某个 ARM 寄存器用作 操作数,它就成为相同名称的虚拟寄存器的引用,而不是 对实际物理 ARM 寄存器的引用。例如内联汇编指令中使 用了寄存器r0,但对于C编译器,指令中出现的r0只是一 个变量,并非实际的物理寄存器r0,当程序运行时,可能
编译器使用一套规则的来设置寄存器的用法
CPSR 标志位可被函数调用所破坏 一些和编译过的代码交互工作的汇编码在接口层必 须满足的规范
寄存器变量 必须保护
- 如果 RWPI选项有效,作为栈的基地址 - 如果软件堆栈检查有效,作为栈的限制值
Scratch register (corruptible)
Stack Pointer Link Register Program Counter
北京理工大学珠海学院
嵌入式系统设计及应用开发
内联汇编的限制3
持。
⑨ 尽管可以使用通用协处理器指令指定 VFP 或 FPA 指令,但内联汇编程序不为它们提供直接支
不能用内联汇编代码更改 VFP 向量模式。内联汇
编可包含浮点表达式操作数,该操作数可使用编译
程序生成的 VFP 代码求出操作数值。因此,仅由 编译程序修改 VFP 状态很重要。 ⑩ 内嵌汇编不支持的指令:BX、BLX、BXJ和 BKPT指令。而LDM、STM、LDRD和STRD指令
Chavezwang@gmail.com
计算机学院嵌入式实验室
5
北京理工大学珠海学院
嵌入式系统设计及应用开发
注意
源文件中段之间的相对位置与可执行的映 像文件中段的相对位置可能不相同
ZI RO-DATA RW RO-CODE CODE B
A
RO
Chavezwang@gmail.com
计算机学院嵌入式实验室
END
这里所有的参数都是可以用寄存器来传递的,所以不需要在汇编程序中使用 PUSH/POP来保护
计算机学院嵌入式实验室 11
Chavezwang@gmail.com
北京理工大学珠海学院
内联汇编的特点1
嵌入式系统设计及应用开发
Leabharlann Baidu
由于内联汇编嵌入在C或C++程序中,所有在用法上有其自身的一些特点。 ① 如果同一行中包含多条指令,则用分号隔开。
③ 不能在程序中使用“.”或{PC}得到当前指令地址值。
④ 在16进制常量前加“0x”。
⑤ 建议不要对堆栈进行操作。
Chavezwang@gmail.com
计算机学院嵌入式实验室
16
北京理工大学珠海学院
嵌入式系统设计及应用开发
内联汇编的限制2
⑥ 编译器可能会使用r12和r13寄存器存放编译的中间结果, 在计算表达式值可能会将寄存器r0~r3、r12及r14用于子程 序调用。另外在内联汇编中设置程序状态寄存器CPSR中的 标志位NZCV时,要特别小心。内联汇编中的设置很可能会 和编译器计算的表达式的结果冲突。
extern void mystrcopy(char *d, const char *s); int main(void) { const char *src = “Source”; char dest[10]; CALL ... mystrcopy(dest, src); ... }
mystrcopy LDRB r2, [r1], #1 STRB r2, [r0], #1 CMP r2, #0 BNE mystrcopy MOV pc, lr
Chavezwang@gmail.com 计算机学院嵌入式实验室 14
北京理工大学珠海学院
嵌入式系统设计及应用开发
内联汇编( Inline assembler
使用C变量代替寄存器
/* Q flag is bit 27 of PSR */ const int Q_Flag=0x08000000; __inline int Clear_Q_flag (void) { int old_psr, new_psr, result;
- r14值压栈以后,r14可作为一个临时寄存器使用
Chavezwang@gmail.com
计算机学院嵌入式实验室
10
北京理工大学珠海学院
嵌入式系统设计及应用开发
在C程序中调用汇编
在汇编程序中用export name来定 义 在C程序中直接调用 一般的链接即可
AREA StringCopy, CODE, READON EXPORT mystrcopy
合内联汇编的语法规 则。 int f(int x) { STMFD sp!, {r0} ADD r0, x, 1 EOR x, r0, x // 保存r0 – 不合法,因 int r0; __asm { 为在读之前没有对寄存器寄存器写操作
{
__asm
{ ADD r0, x, 1
LDMFD sp!, {r0}
Chavezwang@gmail.com 计算机学院嵌入式实验室 20
{
test_inline_register (); printf("test inline register\n");
return 0; }
北京理工大学珠海学院
嵌入式系统设计及应用开发
test_inline_register: 输出结果
⑥ 内联汇编中的寄存器(除程序状态寄存器CPSR和SPSR外)在读取前必 须先赋值,否则编译器将产生错误信息。
Chavezwang@gmail.com
计算机学院嵌入式实验室
12
北京理工大学珠海学院
嵌入式系统设计及应用开发
错误的内联汇编函数如下所示。 int f(int x)
内联汇编与汇编之间的区别 将其进行改写,是它符
IAR汇编器支持的伪指令 简单汇编语言程序设计
Chavezwang@gmail.com
计算机学院嵌入式实验室
3
北京理工大学珠海学院
嵌入式系统设计及应用开发
汇编语言程序设计规范-段
段:相对独立的指令或数据序列,具有特点的名 称 段:
– –
代码段:内容为执行代码 数据段:存放代码代码运行时需要用到 的数据
⑦ 可以使用内联汇编代码更改处理器模式。然而,更改处理
器模式会禁止使用 C或 C++ 操作数或对已编译 C 或 C++ 代码的调用,直到将处理器模式更改回原设置之后之前的函
数库才可正常使用。
⑧ 为 Thumb 状态编译 C 或 C++ 时,内联汇编程序不可用且 不汇编 Thumb 指令。
Chavezwang@gmail.com 计算机学院嵌入式实验室 17
6
混合使用C/C++/汇编
北京理工大学珠海学院
嵌入式系统设计及应用开发
混合使用C/C++/汇编
内联汇编和嵌入型汇编的使用 从汇编代码访问 C 全局变量 在C++中使用C头文件 C、C++ 和 ARM 汇编语言之间的调用
Chavezwang@gmail.com
计算机学院嵌入式实验室
8
计算机学院嵌入式实验室 15
Chavezwang@gmail.com
北京理工大学珠海学院
嵌入式系统设计及应用开发
内联汇编的限制1
可以在内联汇编代码中执行的操作有许多限制。这些限 C++ 代码编译中的规则。 ① 不能直接向程序计数器PC赋值。 ② 内联汇编不支持标号变量。
制提供安全的方法,并确保在汇编代码中不违反 C 和
是由物理寄存器r1来存放r0所代表的值。
Chavezwang@gmail.com
计算机学院嵌入式实验室
19
北京理工大学珠海学院
嵌入式系统设计及应用开发
内联汇编中虚拟寄存器举例
int main(void) #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 } }
多个段在程序编译链接时最终形成一个可执行的 代码段
计算机学院嵌入式实验室 4
Chavezwang@gmail.com
北京理工大学珠海学院
嵌入式系统设计及应用开发
段的设置规则
一个或多个代码段,代码段的属性为只读 0个或多个包含初始化数据的数据段,数据 段的属性为可读/写 0个或多个不包含初始化数据的数据段,数 据段的属性为可读/写
② 如果一条指令不能在一行中完成,使用反斜杠“/”将其连接。
③ 内联汇编中的注释语句可以使用C或C++风格的。 ④ 汇编语言中使用逗号“,”作为指令操作数的分隔符,所以如果在C语 言中使用逗号必须用圆括号括起来。如,__asm {ADD x, y, (f(), z)}。 ⑤ 内联汇编语言中的寄存器名被编译器视为C或C++语言中的变量,所以内 联汇编中出现的寄存器名不一定和同名的物理寄存器相对应。而且这些 寄存器名在使用前必须声明,否则编译器将提示警告信息。
0000807C E3A00000 MOV r0,#0 >>> TEST_INLINE_REGISTER\#12 loop: 00008080 E1A00000 NOP >>> TEST_INLINE_REGISTER\#13 MOV 00008084 E3A01000 MOV r1,#0 >>> TEST_INLINE_REGISTER\#14 MOV 00008088 E3A02000 MOV r2,#0 >>> TEST_INLINE_REGISTER\#15 MOV 0000808C E3A03000 MOV r3,#0 >>> TEST_INLINE_REGISTER\#16 ADD 00008090 E2800001 ADD r0,r0,#1 >>> TEST_INLINE_REGISTER\#17 CMP 00008094 E3500003 CMP r0,#3 00008098 0A000000 BEQ 0x80a0 <TEST_INLINE_REGISTER\#21> >>> TEST_INLINE_REGISTER\#18 BNE 0000809C EAFFFFF8 B 0x8084 <TEST_INLINE_REGISTER\#13> >>> TEST_INLINE_REGISTER\#21 } 计算机学院嵌入式实验室 Chavezwang@gmail.com 000080A0 E12FFF1E BX r14
不是一个真正的汇编文件
通过优化器实现 代码可能被改变
只支持在ARM 模式 (not Thumb) 可以有自己独立的函数,但通 常是内嵌在C函数中
__asm
{ MRS old_psr, CPSR BIC new_psr, old_psr, #Q_Flag AND result, old_psr, #Q_Flag MSR CPSR_f, new_psr } return result; }
北京理工大学珠海学院
嵌入式系统设计及应用开发
何时使用内联汇编和嵌入型汇编
程序中使用饱和算术运算(Saturating arithmetic),如SSAT16 和 USAT16指令。
程序中需要对协处理器进行操作。 在C或C++程序中完成对程序状态寄存器的操作
注:使用内联汇编编写的程序代码效率也比较高
ARM 汇编语言程序 设计
北京理工大学珠海学院
嵌入式系统设计及应用开发
特别说明
开发工具不同所以的 编译语言伪指令不同
– – –
GCC ADS IAR
Chavezwang@gmail.com
计算机学院嵌入式实验室
2
北京理工大学珠海学院
嵌入式系统设计及应用开发
汇编语言程序设计
汇编程序设计规范