error: A1284E: Literal pool too distant, use LTORG to assemble it within 4KB

作者:fly 发布于:2014-4-24 15:39 分类:嵌入式

转载请标明出处,本文转自 www.forwhat.cn

在大型段中,默认的文字池可能会超出一个或多个 LDR 指令的范围。从程序计数器到该常数的偏移量必须是:在 ARM 状态中小于 4KB但可以沿每个方向;需要指出的是,文字池是汇编时自己建立的。


对于上句红色的理解,可以有个一段代码来说明:


       AREA ARMex, CODE, READONLY  ; name this block of code


       ENTRY                       ; mark first instruction to execute


start


       MOV     r0, #10             ; Set up parameters


       MOV     r1, #3


LDR     r1, =0


       ADD     r0, r0, r1          ; r0 = r0 + r1


stop


       MOV     r0, #0×18           ; angel_SWIreason_ReportException


       LDR     r1, =0×20026        ; ADP_Stopped_ApplicationExit


       SWI     0×123456            ; ARM semihosting SWI


LargeTable


       SPACE   4200                    ; Clears a 4200 byte area of memory,


                                       ; starting at the current location,


                                       ; to zero.


       END                         ; Mark end of file


这样再编译的时候,就会有错误产生


Error:A1284E: Literal pool too distant,use LTORG to assmble it within 4k


这是因为SPACE产生了4200byte的空间,文字池就不能在4k之后,也就是SPAPE后建立。


以上的蓝色部分说可以沿每个方向,但不是说可以在LDR指令的上面建立文字池。


如一下代码可以说明


       AREA Loadcon, CODE, READONLY


       ENTRY                           ; Mark first instruction to execute


start


       BL      func1                   ; Branch to first subroutine


       BL      func2                   ; Branch to second subroutine


stop


       MOV     r0, #0×18               ; angel_SWIreason_ReportException


       LDR     r1, =0×20026          ; ADP_Stopped_ApplicationExit


       SWI     0×123456                ; ARM semihosting SWI      


func1


       LDR     r0, =42                 ; => MOV R0, #42


       LDR     r1, =0×55555555         ; => LDR R1, [PC, #offset to Literal Pool 1]


       LDR     r2, =0xFFFFFFFF         ; => MVN R2, #0


       MOV     pc, lr


       LTORG                           ; Literal Pool 1 contains


                                              ; literal &55555555


func2


       LDR     r3, =0×55555555         ; => LDR R3, [PC, #offset to


                                                       ; Literal Pool 1 is out of reach


       MOV     pc, lr


LargeTable


       SPACE   4200                    ; Clears a 4200 byte area of memory,


                                                 ; starting at the current location, to zero.


       END                                  ; Literal Pool 2 is empty


以上代码是可以编译通过的,注意LTORG这个命令,它的作用为


如果下一个文字池超出范围,汇编程序将产生一条出错信息。在这种情况下,必


须使用 LTORG 命令来在代码中放置一个附加的文字池。将 LTORG 命令放在失败 LDR


伪指令后,并且在 4KB (ARM) 或 1KB (Thumb) 范围内。


所以,LTORG产生了一个文字池在MOV pc, lr后来存放0x55555555,0xFFFFFFFF。不然编译就会报错,因为有SAPCE产生的4200byte空间,可以由反汇编看出


start         [0xeb000003]   bl          func1


00008004 [0xeb000008]   bl          func2


stop          [0xe3a00018]   mov     r0,#0×18


0000800c [0xe59f1010]    ldr        r1,0×00008024 ; = #0×00020026


00008010 [0xef123456]    swi       0×123456


func1        [0xe3a0002a]   mov     r0,#0x2a


00008018 [0xe59f1008]    ldr        r1,0×00008028 ; = #0×55555555


0000801c [0xe3e02000]   mvn      r2,#0


00008020 [0xe1a0f00e]   mov      pc,r14


00008024 [0x00020026]  dcd      0×00020026  &…


00008028 [0x55555555]  dcd      0×55555555  UUUU


func2        [0xe51f300c]   ldr       r3,0×00008028 ; = #0×55555555


00008030 [0xe1a0f00e]   mov    pc,r14


但如果改变fun2中的LDR r3, =0×55555555,为其他值,如0×66666666,则编译会报错,所以LDR向上只是寻找文字池中相同的数字,而不能向上创建文字池,如果没有,就向下创建,如上代码是不能创建的,所以改数值后,编译会报同样的错误。


把fun2改为


func2


       LDR     r3, =0×55555555         ; => LDR R3, [PC, #offset to


                                                       ; Literal Pool 1]


       LDR r4, =0xe1a0f00e             ; If this is uncommented it


                                                      ; fails, because Literal Pool 2


                                                      ; is out of reach


       MOV     pc, lr


这样加上LDR r4, =0xe1a0f00e 就会报错,原因已经说明,只要在MOV pc,lr后面加上LTORG即可,但是不能在前面加,编译会通过,但是会有警告


Warning : A147W:directive LTORG may be in an executable position


这是说文字池在执行代码段中,反汇编可以看到


func2        [0xe51f300c]   ldr       r3,0×00008028 ; = #0×55555555


00008030 [0xe51f4004]   ldr       r4,0×00008034 ; = #0xe1a0f00e


00008034 [0xe1a0f00e]   dcd     0xe1a0f00e  ….


00008038 [0xe1a0f00e]   mov    pc,r14


pc指针指引到ldr r4,0×00008034后就会执行下一地址的指令,0xe1a0f00e显然不是一条机器指令,不过可以执行下去,但是数值刚好和某条机器指令相同,就会产生意想不到的结果。

 

发表评论:

 
Powered by emlog sitemap