|
|
51CTO旗下网站
|
|
移动端

1.6.2 汇编实现

《ARM嵌入式系统编程与优化》第1章Linux/ARM嵌入式平台,本章介绍如何使用GCC编译器、汇编器和连接器来编写和执行独立的汇编语言程序,以及如何将一个C语言代码和汇编语言代码合起来,以验证汇编代码子程序的正确性。本节为大家介绍汇编实现。

作者:梁元宇 译来源:机械工业出版社|2017-09-26 19:07

1.6.2 汇编实现

使用“.equ”汇编指令来定义常数N:

使用“.comm”汇编指令为数据数组分配空间。创建名为“data”、大小为N*4的数组,并且其起始地址是在4字节边界对齐(平均被4整除)。

接下来,使用“.global”指令告诉汇编器导出主函数(之后会定义),这样它可以被静态链接,并被Linux运行时环境调用:

最后,使用“.arch”指令告诉汇编器产生ARMv7-A机器语言。

以带有“main”标签的主函数开始,使用第一个指令设置寄存器r1为外层和内层循环的迭代次数。第一个指令将执行如下内容:

1)加载定义N的值进入寄存器r1。

2)这个寄存器递减1。

通过外层循环计数器分配变量i到寄存器r5中并将其初始化为0,开始外层for循环:

内外循环均为for循环。for循环是先测试循环,因此它们首先用一个测试来确定是否应该执行循环体。这种情况下,比较外循环计数器的值是否是范围值,它们被分别存放在寄存器r5和r1中。如果这些值是相等的,则退出循环:

外循环体由内循环构成,内循环可以精确地设置外循环。使用寄存器r3存放内循环计数器:

此外,初始化循环计数器为0,并为数组初始化一个基础寄存器:

在C代码的直译中,内循环将加载元素j和j + 1到两个寄存器,并进行比较,如果有必要,则以相反的顺序存储它们。但是,内循环的每一次迭代只需要加载元素j + 1,因为元素j可以在前一个迭代中使用到。

内循环将元素j分配到寄存器r11,将元素j + 1分配到寄存器r10。这个寄存器数字的顺序刚好相反,在存储器中交换值(stm指令要求的)时,使用多重存储(stm)指令按顺序存储寄存器。

在启动内部循环之前,程序必须预加载第一个元素。

添加循环测试:

内循环体加载数组中的值(相当于元素j + 1),与元素j进行比较,并将它们存储到数组中,如果有必要,则以相反顺序存储。

用寄存器r2作为基本寄存器存储数组中的当前位置。当加载元素j + 1时,使用预增长寻址模式加载第二个值,并将地址更新到寄存器r2中:

比较这些值。元素j大于元素j + 1的条件将作为断定是否倒序储存值的依据。

在存储元素时使用多重存储指令。

如果程序以倒序存储值,r11原本代表元素j当前值,现在则在数组中移动一个位置,实际上就成了元素j + 1个。这个值将被视为在下一次迭代中的元素j,因此程序为了进行下一次迭代将把它放在寄存器r11。

如果值没有交换,为了循环的下一次迭代,将会复制寄存器r10的值到寄存器r11中。此条件是小于或等于(le),大于是逻辑补。

在内循环体后增加数组索引寄存器和内循环计数器,然后将分支返回到循环的起始点。

在退出内循环时,对外循环也做同样的事情:

在退出外循环时,通过跳转到链接寄存器中的存储位置来返回主函数:

使用gcc和time编译这个代码:

汇编实现需要3.6s,比编译器生成的版本快了11%。


喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:365934973

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

精通Spring 2.0

本书是关于Spring 2.0的权威教程,是Java/Java EE开发者必备的参考书。本书详尽系统地介绍了Java EE的基础知识、Spring 2.0的各种功能,以...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊