這個問題在這里已經有了答案:
000080ec ldr r3, [pc, #76] -> 0x813c = 0x80f0 0x4c -> pc = 80f0 ?? (shouldnt it be 80ee).
000080ee cmp r3, #0
000080f0 it eq
000080f2 ldreq r3, [pc, #68] -> 0x8138 = 0x80f4 0x44 -> pc = 80f4 (this makes sense).
000080f4 mov sp, r3
000080f6 sub.w sl, r3, #65536 (edited)
這也發生在代碼的下方,并不總是 pc 保存要執行的下一條指令的地址..有什么我應該考慮的嗎?
uj5u.com熱心網友回復:
您缺少的關鍵是PCThumbldr Rd, [Pc, #imm]指令中的值在使用前對齊到 4 個位元組。ARMv7 架構參考手冊中略有刪節的偽代碼是:
t = UInt(Rt);
imm32 = ZeroExtend(imm8:’00’, 32);
base = Align(PC,4);
address = base imm32;
data = MemU[address,4];
R[t] = data;
所以回到你的例子:
000080ec ldr r3, [pc, #76]
我們知道PC在 Thumb 模式下讀取為當前地址加 4 個位元組,因此 PC 讀取為0x80f0. 此值已對齊到 4 個位元組,因此base具有相同的值。為此我們添加76(立即數總是四的倍數,兩個最低有效位未存盤)得到0x813c.
對于第二個例子:
000080f2 ldreq r3, [pc, #68]
這與ldr上面的指令相同。反匯編器eq向助記符添加后綴,因為指令受前一個IT塊的有條件執行的約束。但這不會以任何方式影響指令編碼。
PC讀取為0x80f6與 4 個位元組對齊的0x80f4. 為此,我們添加68, 獲取0x8138作為加載地址。
有關詳細資訊,請參閱 ARM 體系結構參考手冊。
uj5u.com熱心網友回復:
pc 相關 ldr 指令的拇指編碼最近剛剛在 SO 上進行了介紹。當您查看有關指令集的檔案時,正如我們已經指出的那樣,您會知道 PC 從檔案的角度來看,在前 thumb2 天的早期領先兩個,但現在拇指比指令地址領先 4 個位元組. pc 偏移量以字為單位進行編碼,因此使用的地址是
((instruction address 4 ) & 0xFFFFFFFC) (immed<<2)
消除對前面兩件事的所有困惑。
現實情況是有多個程式計數器,用于實際獲取事物和進行 pc 相對尋址的單個程式計數器的時代已成為較舊、更簡單的體系結構歷史的一部分。
這兩個前面的東西是過去的一部分,但出于兼容性原因,從 acorn 一直延續到現在的 arm 產品,就像 x86 和其他人有遺留的東西,不再是他們所說的那樣(branch shadow/defer slot in mips)。
管道是不同的,對于每個不同的 arm 產品(不是架構,而是產品 cortex-m0、cortex-m4、cortex-a7 等),管道的實作以及核心如何跟蹤事物都會有所不同。前面的兩個由某種形式的程式計數器合成,用于跟蹤管道中的指令。同樣,取/預取/分支預測都是程式計數器的形式,但不假定為單個程式計數器。r15 本身也是來自暫存器檔案的真實或假的或兩者兼而有之(我希望不在暫存器檔案中,為什么要燒掉這些周期而不增加任何價值)。
就像在軟體中你可以有一個 reg[15] 陣列項、一個 pc_fetch、一個 pc_current_inst、pc_execution、一個 pc_possible_branch、一個 pc_branch_prediction 變數集來跟蹤處理器的模擬,邏輯也可以。什么時候使用哪一個取決于你在做什么。正如在指令的操作中所描述的那樣,我們作為程式員的 PC 所關心的是一個地址,該地址比指令所在的地址“提前兩個”。使用thumb2 前面的兩個不再有意義,因此對于thumb 模式,它比arm 模式提前4 個位元組,比指令地址提前8 個位元組。然后您可以按照檔案了解在執行指令期間如何使用該 PC。
對于 BX 和其他能夠模式切換的指令,成為“程式計數器”的那個地址的定義是不同的,lsbit 驅動模式切換到(并被它不在程式計數器中的分支剝離,有是一個 psr 位來照顧它)。這些地址也是程式計數器的一種形式,至少暫時是要跳轉到的指令的實際地址,而不是前面兩個。
在許多早期的處理器實作中,你有一個或一個程式計數器的想法,在繼續下一條指令之前,你一次獲取、解碼和執行一條指令(并不意味著人們不再做這些設計,你可以讓小而高效的小控制器是老式的方式,人們仍然這樣做,并且在我們使用的產品中)。在這種情況下,pc 用于獲取指令,該指令可能超過一個位元組,一旦指令被完全獲取,則程式計數器至少在目前指向下一條指令。由于提取和解碼已經完成,現在可以開始執行該指令。如果程式計數器用作該指令的輸入,則它指向下一條指令,如果用作跳轉或分支中的目的地,那么它會被修改,并在完成后下一次獲取發生在它碰巧指向的任何地方。這些架構中的許多都是可變長度指令集,因此,一條指令可能是一、二、三……位元組長,因此在執行時相對于指令地址的 pc 地址是不同的。早期的 arm 來自具有固定大小指令的管道型別解決方案,所以如果你有一個單一的程式計數器,那么,根據管道設計,如果你使用教科書風格的,那么執行是在管道中的固定深度當您執行時,程式計數器會提前獲取那么多。位元組長,因此 pc 地址相對于執行時的指令地址,有所不同。早期的 arm 來自具有固定大小指令的管道型別解決方案,所以如果你有一個單一的程式計數器,那么,根據管道設計,如果你使用教科書風格的,那么執行是在管道中的固定深度當您執行時,程式計數器會提前獲取那么多。位元組長,因此 pc 地址相對于執行時的指令地址,有所不同。早期的 arm 來自具有固定大小指令的管道型別解決方案,所以如果你有一個單一的程式計數器,那么,根據管道設計,如果你使用教科書風格的,那么執行是在管道中的固定深度當您執行時,程式計數器會提前獲取那么多。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/398681.html
