首先來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<span style="white-space:pre"> </span>;通過pc 來加上 dcd 的<span style="font-family: Arial, Helvetica, sans-serif;">handleBuf_ptr 於當前的位置偏移來獲取變量地址</span>
ldr r3,[r3] ;對<span style="font-family: Arial, Helvetica, sans-serif;">handleBuf_ptr進行取值,獲得最終buf的地址,存到r3</span>
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)結果不對
具體原因,這部分要看編譯器如何處理。不深究,不同編譯器處理有些許差異。