26
? (5)SWI和BL指令
? SWI和BL指令用于内嵌汇编时,除了正常的操作数域外,还必须增加如下3个可
选的寄存器列表:
? 用于存放输入的参数的寄存器列表。 ? 用于存放返回结果的寄存器列表。
? 用于保存被调用的子程序工作寄存器的寄存器列表。
第8章 ARM汇编语言与嵌入式C混合编程
1.严格按照嵌入式C语言的编程规范,写一个C语言程序,实现将一个二维数组内的数据行和列进行排序。 答:略
2.嵌入式C程序设计中常用的移位操作有哪几种,请说明每种运算所对应的ARM指令实现。 答:移位操作分为左移操作与右移操作
左移运算符―<<‖实现将―<<‖左边的操作数的各个二进制位向左移动―<<‖右边操作数所指定的位数,高位丢弃,低位补0。其值相当于乘以:2―左移位数‖次方。
右移运算符―>>‖实现将―>>‖左边的操作数的各个二进制位向右移动―<<‖右边操作数所指定的位数。
? 对于空位的补齐方式,无符号数与有符号数是有区别的。
? 对无符号数进行右移时,低位丢弃,高位用0补齐,其值相当于除以:2―右移位数‖
次方
? 对有符号数进行右移时,根据处理器的不同选择逻辑右移或算术右移
3.volatile限制符在程序中起到什么作用。请举例说明。
答:volatile的本意为 ―暂态的‖或.―易变的‖,该说明符起到抑制编译器优化的作用。
如果在声明时用―volatile‖关键进行修饰,遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供特殊地址的稳定访问。 ? 例:硬件端口寄存器读取 ? Char x=0,y=0,z=0;
? x=ReadChar(0x54000000);//读端口 ? y=x;
? x=ReadChar(0x54000000);//再读端口 ? z=x;
? 以上代码可能被编译器优化为 ? Char x=0,y=0,z=0;
? x=ReadChar(0x54000000);//读端口 ? y=x; ? z=x;
? 为了确保x的值从真实端口获取,声明时应该为 ? Volatile char x; ? Char y,z;
26
27
4.请分析下列程序代码的执行结果。 #include
答:程序输出结果为:****p4=4081
5.分析宏定义#define POWER(x) x*x 是否合理,举例说明。如果不合理,应如何更改? 答:#define POWER(x) x*x 不合理;对于带参数的宏,其参数应该用括号括起来。 例:如果按照下边方式使用该宏
POWER(2+3) 则宏展开后为 2+3*2+3
该宏应修改为:#define POWER(x) (x)*(x)
6.条件编译在程序设计中有哪些用途?
答:条件编译包括了6条预处理指令#ifdef, #ifndef. ##if, #elif, #else, #endif.。条件编译的功能在于对源程序中的一部分内容只有满足某种条件的情况下才进行编译。
7.何为可重入函数?如果使程序具有可重入性,在程序设计中应该注意哪些问题?
答:如果某个函数可以被多个任务并发使用,而不会造成数据错误,我们就说这个函数具有可重入性(reentrant) 。
可重入函数可以使用局部变量,也可以使用全局变量。
如果使用全局变量,则应通过关中断、信号量(即P、V操作)等手段对其加以保护,若不加以保护,则此函数就不具有可重入性,即当多个进程调用此函数时,很有可能使得此全局变量变为不可知状态。
8.现有模块module_1, module_2, module_3, 要求在模块module_1中提供可供模块module_2, module_3使用的int型变量xx,请写出模块化程序设计框架。 答:首先在module_1的.c文件中定义 int xx; /*module_1.c*/ int xx=0;
然后在module_1的.h 文件中声明xx为外部变量 /*module_1.h*/ extern int xx;
接下来在module_2源文件中包括module_1的 .h 文件 /*module_2.c*/
#include \
在module_3源文件中包括module_1的 .h 文件 /*module_3.c*/
27
28
#include \
这样在module_2, module_3中就可以使用module_1中提供的int型变量xx了。
9.ATPCS 与 AAPCS的全称是是什么,它们有什么差别?掌握子程序调用过程中寄存器的使用规则,数据栈的使用规则及参数的传递规则,在具体的函数中能够熟练应用。
答:过程调用标准ATPCS(ARM-Thumb Produce Call Standard)规定了子程序间相互调用的基本规则, ATPCS规定子程序调用过程中寄存器的使用规则、数据栈的使用规则及参数的传递规则。
2007年,ARM公司推出了新的过程调用标准AAPCS(ARM Architecture Produce Call Standard),它只是改进了原有的ATPCS的二进制代码的兼容性。
10.内嵌式汇编有哪些局限性?编写一段代码采用C语言嵌入式汇编程序,在汇编程序中实现字符串的拷贝操作。 答:内嵌汇编的局限性
(1)操作数
? ARM开发工具编译环境下内嵌汇编语言,指令操作数可以是寄存器、常量或C语
言表达式。可以是char、short或int类型,而且是作为无符号数进行操作。 ? 当表达式过于复杂时需要使用较多的物理寄存器,有可能产生冲突。
? GNU ARM编译环境下内嵌汇编语言ARM开发工具稍有差别,不能直接引用C语
言中的变量。 (2)物理寄存器
不要直接向程序计数器PC赋值,程序的跳转只能通过B或BL指令实现。
一般将寄存器R0~R3、R12及R14用于子程序调用存放中间结果,因此在内嵌汇编指令中,一般不要将这些寄存器同时指定为指令中的物理寄存器。
在内嵌的汇编指令中使用物理寄存器时,如果有C语言变量使用了该物理寄存器,则编译器将在合适的时候保存并恢复该变量的值。需要注意的是,当寄存器SP、SL、FP以及SB用作特定的用途时,编译器不能恢复这些寄存器的值。
通常在内嵌汇编指令中不要指定物理寄存器,因为有可能会影响编译器分配寄存器,进而可能影响代码的效率。 (3)标号、常量及指令展开
? C语言程序中的标号可以被内嵌的汇编指令所使用。但是只有B指令可以使用C语
言程序中的标号,BL指令不能使用C语言程序中的标号。 (4)内存单元的分配
? 内嵌汇编器不支持汇编语言中用于内存分配的伪操作。所用的内存单元的分配都是
通过C语言程序完成的,分配的内存单元通过变量以供内嵌的汇编器使用。 ? (5)SWI和BL指令
? SWI和BL指令用于内嵌汇编时,除了正常的操作数域外,还必须增加如下3个可
选的寄存器列表:
? 用于存放输入的参数的寄存器列表。 ? 用于存放返回结果的寄存器列表。
? 用于保存被调用的子程序工作寄存器的寄存器列表。
28