首页 > 版块 > STM32 > 帖子正文

一文带你读懂ARM文字池

蔡琰 发布于 2021-10-13 17:00
收藏 0 回复 0 浏览 92 原创

说到文字池,首先第一个问题:什么是文字池?文字池又叫literal pool,它的本质就是ARM汇编语言代码节中的一块用来存放常量数据而非可执行代码的内存块。


那为什么要使用文字池呢?当想要在一条指令中使用一个 4字节长度的常量数据(这个数据可能是内存地址,可能是数字常量)的时候,由于ARM指令集是定长的(ARM指令4字节或Thumb指令2字节),就无法把这个4字节的常量数据编码在一条编译后的指令中。此时,ARM编译器(编译C源程序)/汇编器(编译汇编程序) 就会在代码节中分配一块内存,并把这个4字节的数据常量保存起来,之后,再使用一条指令把这个4 字节的数字常量加载到寄存器中参与运算。 C程序中,文字池的分配是由编译器在编译时自行分配安排的,但是,汇编程序时,开发者可以自己进行文字池的分配,当然如果没有自己分配汇编器会代劳。不管何种情况,这不影响我们来了解学习一下文字池的知识。


LDR Rd,=const 伪指令可在单个指令中构造任何 32 位数字常数。 使用此伪指令可生成超出MOVMVN指令范围的常数。LDR 伪指令可为特定的常数生成最高效的单个指令:如果可以用单个MOVMVN 指令构造该常数,则汇编器会生成适当的指令。如果不能用单个MOVMVN 指令构造该常数,则汇编器会执行下列操作:将该值放入文字池中生成一个使用程序相对地址的 LDR 指令,用于从文字池中读取该常数。说的通俗一点,如果LDR Rd, =const能够被转换成MOV 或者MVN指令,则汇编器将转换成它成为相应的指令,如果不能被转换,则汇编器会将value存放在文字池中,并且产生一个LDR指令操作。


汇编器默认把文字池放在每一个代码节的末尾处。代码节的末尾的确定或者是由汇编源文件尾部的指示符END确定或者由相邻代码节的起始行AREA确定。在大的代码节中(通俗理解为这个节中的代码量比较大),默认文字池在最后,可能与代码节中一条或多条LDR伪指令的距离很远,可能超出LDR伪指令操作数的寻址范围。


当伪指令是32位时,在ARMThumb代码中,必须小于4K字节,文字池常量数据的位置可以是在伪指令的前面,也可以是在伪指令的后面当伪指令是16Thumb指令时,必须小于1K字节,且文字池必须位于伪指令的后面。


LDR  Rd, =const 伪指令需要一个文字池来存放立即数常量时,汇编器检查已经存在文字池中是否有相同的常量并且检查文字池是否在伪指令允许寻址范围内。如果条件满足,汇编器引用这个满足条件的常量,否则汇编器会尝试把该常量值放到文字池未用的空间中。如果空间地址超出伪指令的寻址范围,汇编器会产生一条错误信息。这种情况下,程序员必须得自己用指示符LTORG在代码中设置增加一个文字池。指示符LTORG放在导致错误的伪指令后面,并且位于伪指令LDR的有效寻址范围内(一般节的代码量不是特别大的情况下,可以放于中间位置)而且要保证设置的这个文字池,处理器执行代码的时候不会执行到这个地址。 它们应放在无条件跳转指令的后面,或者放在子例程末尾处的返回指令的后面。


应用举例如下:

Fun1
    LDR R0, =0X12345678
    ADD R1, R1, R0
 
   
BX  LR    ;子程序返回
    LTORG    ;声明文字池
,存储0x12345678

POOL  SPACE  20
 
好了,关于文字池,本片文章就讲到这里了,大家有不明白的地方可以留言提问哦,谢谢大家。

0 0
发表评论 侵权投诉
评论 (0)

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表乌云踏雪网立场。

文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。