文字池(Literal pools)其实就是一个存储常量数据的地方,汇编器会使用文字池来在代码段中存储常量数据。有时候你需要配合使用LTORG来确保文字池是在程序能够寻址的访问内。
汇编器会在每个段的末尾放置文字池,怎么判断是段的末尾,出现END之后或者出现AREA之前(被include的文件中的END并不算)
在一个大的代码段中,有可能默认的文字池位置是超出LDR能访问的范围的。LDR中相对PC的偏移值需要符合下面条件才是能寻址的(LDR rn, [pc, #offset])
- 在32位的A32/T32中,LDR相对当前PC值的offset不能超过4KB
- 在16位的T32中,LDR相对当前PC值的offset不能超过1KB
使用 LDR Rd,=const这条伪指令处理时,常量需要放置在文字池中,汇编器的具体寻址过程如下:
- 确认const值是否在之前的文字池中,如果是则在找到的文字池中去引用该值
- 如果在之前的文字池中未找到,则在下一个文字池中放置该值,并从该地方引用。如果下一个文字池超出了LDR的寻址范围则需要在LDR能寻址的有效范围内,放置LTORG来强制立即生成一个文字池,确认能够正常编译。当然LTORG不是随便放置的,随便放置有可能被当成汇编指令来执行,需要放置在无条件跳转的汇编指令之后或者子程序还回汇编指令之后。
下面是参考文档的一个例子:
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, #0x18 ; angel_SWIreason_ReportException
LDR r1, =0x20026 ; ADP_Stopped_ApplicationExit
SVC #0x123456 ; A32 semihosting (formerly SWI)
func1
LDR r0, =42 ; => MOV R0, #42
LDR r1, =0x55555555 ; => LDR R1, [PC, #offset to
; Literal Pool 1]
LDR r2, =0xFFFFFFFF ; => MVN R2, #0
BX lr
LTORG ; Literal Pool 1 contains
; literal Ox55555555
func2
LDR r3, =0x55555555 ; => LDR R3, [PC, #offset to
; Literal Pool 1]
; LDR r4, =0x66666666 ; If this is uncommented it
; fails, because Literal Pool 2
; is out of reach
BX lr
LargeTable
SPACE 4200 ; Starting at the current location,
; clears a 4200 byte area of memory
; to zero
END ; Literal Pool 2 is inserted here,
; but is out of range of the LDR
; pseudo-instruction that needs it
参考文献
【1】DUI0801I_armasm_user_guide