首先来2个问题
1.编译器如何处理伪指令,例如ldr。首先伪指令不是真实的指令,这样说有些模糊。伪指令的执行者不是arm cpu,而是编译器。这个描述准确点,但是编译器只是把伪
指令做了转化,转化成arm指令,最终还是有arm cpu来执行。在C语言中 #define TEST (5 - 3) 这里(5- 3)会由编译器计算好,将结果放到最终生成的执行程序中,一般在code的.text段,再最终由arm cpu来执行。
2.编译器和arm 在生成PIC位置无关码中,各自做了哪些事情,是我这个demo想去演示。
demo的作用通过一个buf指针,利用pc指针和buf的相对便宜来对buf进行定位,并完成对其中数据的修改。
下载路径:http://download.csdn.net/detail/losting_boy/9620735
AREA addr01, CODE, READONLY
entry
CODE32
start
ldr r0, =(testcode16 + 1)
BX r0
CODE16
testcode16
mov r5,#1
ldr r3,=handleBuf_ptr - 0x8016 ;(1)注意这里
LSLS r5,r5,#2
add r3,pc ;通过pc 来加上 dcd 的handleBuf_ptr 于当前的位置偏移来获取变量地址
ldr r3,[r3] ;对handleBuf_ptr进行取值,获得最终buf的地址,存到r3
tag
movs r1,#0x80 ;这里的地址是0x8016
str r0,[r5,r3]
stop
b .
AREA data1,DATA,READWRITE
handlebuf DCB 1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4
handleBuf_ptr DCD handlebuf
END
注意点:
(1)0x8016怎么来的,由编译器计算得来,这里是我模拟编译器,通过反编译计算得来。
(2)ldr r3,=handleBuf_ptr - 0x8016,因为ldr是伪指令,编译器翻译成了 ldr r3,0x8028,这里0x8028存储的是编译器计算的结果,如下,arm cpu执行从这个地址取结果
(3)thumb pc = 当前执行地址 + 4, code 32 pc = 当前 + 8 ,具体不解释
(4)handlebuf代表一个buf的首地址,handleBuf_ptr是指向handlebuf的指针。这里可以理解为标号,等效于地址。cpu是不区分那些是指针,哪些是指针的指针啥的,只是内存地址和地址中存放的数据
几个坑:
坑1:ldr r3,=handleBuf_ptr - 0x8016 ,换成ldr r3,=(handleBuf_ptr - 0x8016)结果不对
坑2:ldr r3,=handleBuf_ptr - 0x8016 ,换成ldr r3,=(handleBuf_ptr - tag)结果不对
具体原因,这部分要看编译器如何处理。不深究,不同编译器处理有些许差异。