已閱讀5頁,還剩112頁未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
第3章ARM指令系統(tǒng) 硅谷芯微技術(shù)貢獻(xiàn)網(wǎng)址 www threeway cc 面對復(fù)雜多變的ARM匯編指令表 本章重點介紹實用價值大 有一定難度且理解起來容易出錯的指令 以點帶面達(dá)到全面掌握ARM匯編指令的目的 第3章目錄 1 ARM處理器尋址方式2 指令集介紹3 課后練習(xí) 3 1ARM處理器尋址方式 ARM處理器是基于精簡指令集計算機(jī) RISC 原理設(shè)計的 指令集和相關(guān)譯碼機(jī)制較為簡單 ARM9TDMI S 具有32位ARM指令集和16位Thumb指令集 ARM指令集效率高 但是代碼密度較低 而Thumb指令集具有較高的代碼密度 并且保持ARM的大多數(shù)性能上的優(yōu)勢 它是ARM指令集的子集 所有的ARM指令都是可以有條件執(zhí)行的 而Thumb指令僅有一條指令 分支指令B 具備條件執(zhí)行功能 ARM程序和Thumb程序可相互調(diào)用 相互之間的狀態(tài)切換開銷幾乎為零 說明 本章中的ARM9TDMI S 表示ARM9TDMI或ARM9TDMI S 尋址方式是根據(jù)指令中給出的地址碼字段來實現(xiàn)尋找真實操作數(shù)地址的方式 ARM處理器具有8種基本尋址方式 3 1 1寄存器尋址 寄存器尋址是指操作數(shù)的值在寄存器中 指令中的地址碼字段指出的是寄存器編號 指令執(zhí)行時直接取出寄存器值來操作 應(yīng)用示例 3 1 2立即尋址 立即尋址指令中的操作碼字段后面的地址碼部分即是操作數(shù)本身 也就是說 數(shù)據(jù)就包含在指令當(dāng)中 取出指令也就取出了可以立即使用的操作數(shù) 這樣的數(shù)稱為立即數(shù) 應(yīng)用示例 3 1 3寄存器移位尋址 1 寄存器移位尋址是ARM指令集特有的尋址方式 當(dāng)?shù)?個操作數(shù)是寄存器移位方式時 第2個寄存器操作數(shù)在與第1個操作數(shù)結(jié)合之前 選擇進(jìn)行移位操作 應(yīng)用示例 可采用的移位操作如下 LSL 邏輯左移 LogicalShiftLeft 寄存器中字的低端空出的位補(bǔ)0 LSR 邏輯右移 LogicalShiftRight 寄存器中字的高端空出的位補(bǔ)0 ASR 算術(shù)右移 ArithmeticShiftRight 移位過程中保持符號位不變 若源操作數(shù)為正數(shù) 則字的高端空出的位補(bǔ)0 否則補(bǔ)1 3 1 3寄存器移位尋址 2 ROR 循環(huán)右移 ROtateRight 由字的低端移出的位填入字的高端空出的位 RRX 帶擴(kuò)展的循環(huán)右移 RotateRighteXtendedby1place 操作數(shù)右移1位 高端空出的位用原C標(biāo)志值填充 各種移位操作如圖3 1所示 圖3 1移位操作示意圖 3 1 4寄存器間接尋址 寄存器間接尋址指令中的地址碼給出的是一個通用寄存器的編號 所需的操作數(shù)保存在寄存器指定地址的存儲單元中 即寄存器為操作數(shù)的地址指針 應(yīng)用示例 3 1 5基址尋址 基址尋址就是將基址寄存器的內(nèi)容與指令中給出的偏移量相加 形成操作數(shù)的有效地址 基址尋址用于訪問基址附近的存儲單元 常用于查表 數(shù)組操作 功能部件寄存器訪問等 應(yīng)用示例 3 1 6多寄存器尋址 多寄存器尋址是指一次可傳送幾個寄存器值 允許一條指令傳送16個寄存器的任何子集或所有寄存器 應(yīng)用示例 3 1 7堆棧尋址 1 在2 5 1小節(jié)的 堆棧指針 SP 中介紹了堆棧的定義和作用 接下來講述堆棧在ARM9中的特性 前面講過對堆棧操作都是通過堆棧指針 SP 來進(jìn)行的 隨著堆棧內(nèi)容的增減 堆棧指針也做相應(yīng)的移動 那么有個問題 當(dāng)寫入數(shù)據(jù)時堆棧指針是如何變化的呢 堆棧指針的移動方向稱之為 堆棧的生長方向 ARM9可以支持2種 如圖3 2所示 向上生長 在向堆棧寫入數(shù)據(jù)后 堆棧指針的值變大 也就是向高地址方向生長 稱之為遞增堆棧 向下生長 在向堆棧寫入數(shù)據(jù)后 堆棧指針的值變小 也就是向低地址方向生長 稱之為遞減堆棧 3 1 7堆棧尋址 2 圖3 2堆棧的生長方向 3 1 7堆棧尋址 3 除了要考慮堆棧指針的增長方向之外 還要考慮堆棧指針指向的存儲單元是否已經(jīng)保存有堆棧數(shù)據(jù) 或者說在入棧時是否可以直接向堆棧指針指向的存儲單元寫入數(shù)據(jù) ARM9支持2種情況 分別為 滿堆棧 和 空堆棧 如圖3 3所示 滿堆棧 堆棧指針指向最后壓入的有效數(shù)據(jù)項 稱為滿堆棧 這種堆棧的入棧操作要先調(diào)整指針再寫入數(shù)據(jù) 空堆棧 堆棧指針指向下一個待壓入數(shù)據(jù)的空位置 稱為空堆棧 這種堆棧的入棧操作要先寫入數(shù)據(jù)再調(diào)整指針 3 1 7堆棧尋址 4 圖3 3堆棧的滿空特性 3 1 7堆棧尋址 5 綜合前面的堆棧生長方向和堆棧的滿空特性 可以得到4種堆棧類型 分別為 滿遞增 堆棧通過增大存儲器的地址向上增長 堆棧指針指向內(nèi)含有有效數(shù)據(jù)項的最高地址 如指令LDMFA STMFA等 空遞增 堆棧通過增大存儲器的地址向上增長 堆棧指針指向堆棧上的第一個空位置 如指令LDMEA STMEA等 滿遞減 堆棧通過減小存儲器的地址向下增長 堆棧指針指向內(nèi)含有有效數(shù)據(jù)項的最低地址 如指令LDMFD STMFD等 空遞減 堆棧通過減小存儲器的地址向下增長 堆棧指針指向堆棧下的第一個空位置 如指令LDMED STMED等 3 1 7堆棧尋址 6 應(yīng)用示例 3 1 8相對尋址 相對尋址是基址尋址的一種變通 由程序計數(shù)器PC提供基準(zhǔn)地址 指令中的地址碼字段做為偏移量 兩者相加后得到的地址即為操作數(shù)的有效地址 應(yīng)用示例 3 2指令集介紹 本節(jié)介紹ARM9TDMI S 的指令集 包括ARM指令集和Thumb指令集 首先介紹ARM指令的基本格式及靈活的操作數(shù) 然后介紹條件碼 重點介紹ARM指令集 對Thumb指令集 僅作簡要介紹 在介紹ARM指令集之前 先看一個簡單的ARM匯編程序 了解有關(guān)ARM指令匯編格式 程序結(jié)構(gòu)和基本風(fēng)格 完整代碼如程序清單3 1所示 程序清單3 1寄存器相加 第 行為程序說明 使用分號 進(jìn)行注釋 分號 號后面至行結(jié)束均為注釋內(nèi)容 第 行聲明一個代碼段 ARM匯編程序至少要聲明一個代碼段 第 行標(biāo)識程序入口 在仿真調(diào)試時會從指定入口處開始運(yùn)行程序 第 行聲明32位ARM指令 ARM9TDMI S 復(fù)位后是ARM狀態(tài) 第 行為實際代碼 標(biāo)號要頂格書寫 如START LOOP ADD SUB 而指令不能頂格書寫 BL為調(diào)用子程序指令 它會把返回地址 即下一條指令的地址 存到LR 然后跳轉(zhuǎn)到子程序ADD SUB 子程序ADD SUB處理結(jié)束后 將LR的值裝入PC即可返回 第 行為空行 目的在于增強(qiáng)程序的可讀性 第 行用于指示匯編文件結(jié)束 每一個ARM匯編文件均要用END聲明結(jié)束 3 2 1ARM指令集 ARM指令集為32位字對齊指令集 效率高但代碼密度較低 這是本章的重點 3 2 1 1指令格式 1 ARM指令的基本格式如下 S S 其中 號內(nèi)的項是必需的 號內(nèi)的項是可選的 例如是指令助記符 這是必須書寫的 而 為指令執(zhí)行條件 是可選項 若不書寫則使用默認(rèn)條件AL 無條件執(zhí)行 opcode 指令助記符 如LDR STR等 cond 執(zhí)行條件 如EQ NE等 參考表3 1 S 是否影響CPSR寄存器的值 書寫時影響CPSR Rd 目標(biāo)寄存器 3 2 1 1指令格式 2 Rn 第1個操作數(shù)的寄存器 operand2 第2個操作數(shù) 指令格式應(yīng)用舉例 在ARM指令中 靈活地使用第2個操作數(shù)能夠提高代碼效率 第2個操作數(shù)有如下幾種形式 1 immed 8r 常數(shù)表達(dá)式 該常數(shù)必須對應(yīng)8位位圖 pattern 即常數(shù)是由一個8位的常數(shù)循環(huán)移位偶數(shù)位得到的 3 2 1 1指令格式 3 合法常量 0 x3FC 0 xFF 2 0 0 xF0000000 0 xF0 24 200 0 xC8 0 xF0000001 0 x1F 28 非法常量 0 x1FE 511 0 xFFFF 0 x1010 0 xF0000010 常數(shù)表達(dá)式應(yīng)用舉例 2 Rm 寄存器方式 在寄存器方式下 操作數(shù)即為寄存器的數(shù)值 3 2 1 1指令格式 4 寄存器方式應(yīng)用舉例 3 Rm shift 寄存器移位方式 將寄存器的移位結(jié)果作為操作數(shù) 但Rm值保持不變 移位方法如下 ASR n 算術(shù)右移n位 1 n 32 LSL n 邏輯左移n位 1 n 31 LSR n 邏輯右移n位 1 n 32 RRX 帶擴(kuò)展的循環(huán)右移1位 typeRs type為ASR LSL LSR和ROR中的一種 Rs為偏移量寄存器 低8位有效 若Rs值大于或等于32 則第2個操作數(shù)的結(jié)果為0 ASR ROR例外 3 2 1 1指令格式 5 寄存器移位方式應(yīng)用舉例 R15為處理器的程序計數(shù)器PC 一般不要對其進(jìn)行操作 而且有些指令是不允許使用R15的 如UMULL指令 3 2 1 2條件碼 1 使用指令條件碼可實現(xiàn)高效的邏輯操作 提高代碼執(zhí)行效率 所有的指令條件碼如表3 1所列 表3 1指令條件碼列表對于Thumb指令集 只有B指令具有條件碼執(zhí)行功能 此指令的條件碼同表3 1 但如果為無條件執(zhí)行時 條件碼助記符AL不能在指令中書寫 3 2 1 2條件碼 2 應(yīng)用示例 比較兩個值大小 并進(jìn)行相應(yīng)加1處理 C代碼如下 對應(yīng)的ARM指令如下 其中R0為a R1為b 若兩個條件均成立 則將這兩個數(shù)值相加 C代碼如下 3 2 1 2條件碼 3 對應(yīng)的ARM指令如下 其中R0為a R1為b 3 2 1 3ARM存儲器訪問指令 1 ARM處理器是RISC架構(gòu)的處理器 它無法像CISC架構(gòu)的處理器一樣讓存儲器中的內(nèi)容直接參與運(yùn)算 而是需要將存儲單元的內(nèi)容先讀取到內(nèi)部寄存器中 ARM處理器是加載 存儲體系結(jié)構(gòu)的典型RISC處理器 對存儲器的訪問只能使用加載和存儲指令實現(xiàn) ARM的加載 存儲指令可實現(xiàn)字 半字 無符號字節(jié)和有符號字節(jié)的操作 多寄存器加載 存儲指令可實現(xiàn)一條指令加載 存儲多個寄存器的內(nèi)容 大大提高了效率 SWP指令是一條寄存器和存儲器內(nèi)容交換的指令 可用于信號量操作等 ARM處理器是馮 諾依曼體系結(jié)構(gòu) 程序空間 RAM空間及I O映射空間統(tǒng)一編址 對這些空間的訪問均須通過加載 存儲指令進(jìn)行 ARM存儲器訪問指令如表3 2所列 3 2 1 3ARM存儲器訪問指令 2 表3 2ARM存儲器訪問指令 3 2 1 3ARM存儲器訪問指令 3 1 LDR STR 加載 存儲指令 LDR指令用于從內(nèi)存中讀取數(shù)據(jù)放入寄存器中 STR指令則相反 它用于將寄存器中的數(shù)據(jù)保存到內(nèi)存中 LDR和STR指令搭配不同的后綴可以實現(xiàn)字節(jié) 半字或字?jǐn)?shù)據(jù)的訪問 加載 存儲字和無符號字節(jié)指令 指令格式 LDR cond T Rd 加載指定地址上的數(shù)據(jù) 字 放入Rd中STR cond T Rd 存儲數(shù)據(jù) 字 到指定地址的存儲單元 要存儲的數(shù)據(jù)在Rd中LDR cond B T Rd 加載字節(jié)數(shù)據(jù) 放入Rd中 即Rd最低字節(jié)有效 高24位清零 3 2 1 3ARM存儲器訪問指令 4 STR cond B T Rd 存儲字節(jié)數(shù)據(jù) 要存儲的數(shù)據(jù)在Rd 最低字節(jié)有效其中 T為可選后綴 若指令有T 那么即使處理器是在特權(quán)模式下 存儲系統(tǒng)也將訪問看成是處理器是在用戶模式下 T在用戶模式下無效 不能與前索引偏移一起使用T LDR STR指令尋址是非常靈活的 由兩部分組成 一部分為一個基址寄存器 可以為任一個通用寄存器 另一部分為一個地址偏移量 它有3種格式 a 立即數(shù) 立即數(shù)可以是一個無符號的數(shù)值 這個數(shù)據(jù)可以加到基址寄存器 也可以從基址寄存器減去這個數(shù)值 3 2 1 3ARM存儲器訪問指令 5 應(yīng)用示例 b 寄存器 寄存器中的數(shù)值可以加到基址寄存器 也可以從基址寄存器中減去這個數(shù)值 應(yīng)用示例 3 2 1 3ARM存儲器訪問指令 6 c 寄存器與移位常數(shù) 寄存器移位后的值可以加到基址寄存器 也可以從基址寄存器中減去這個數(shù)值 應(yīng)用示例 從尋址方式的地址計算方法分 加載 存儲指令有以下4種形式 零偏移 Rn的值作為傳送數(shù)據(jù)的地址 即地址偏移量為0 應(yīng)用示例 3 2 1 3ARM存儲器訪問指令 7 b 前索引偏移 在數(shù)據(jù)傳送之前 將偏移量加到Rn中 其結(jié)果作為傳送數(shù)據(jù)的存儲地址 若使用后綴 則結(jié)果寫回到Rn中 且Rn的值不允許為R15 應(yīng)用示例 c 程序相對偏移 程序相對偏移是前索引形式的另一個版本 匯編器由PC寄存器計算偏移量 并將PC寄存器作為Rn生成前索引指令 不能使用后綴 應(yīng)用示例 3 2 1 3ARM存儲器訪問指令 8 說明 label為程序標(biāo)號 label必須是在當(dāng)前指令的 4KB范圍內(nèi) d 后索引偏移 Rn的值用作傳送數(shù)據(jù)的存儲地址 在數(shù)據(jù)傳送后 將偏移量與Rn相加 結(jié)果寫回到Rn中 Rn不允許是R15 應(yīng)用示例 地址對齊 大多數(shù)情況下 必須保證用于32位傳送的地址是32位地址對齊的 3 2 1 3ARM存儲器訪問指令 9 加載 存儲半字和有符號字節(jié) 指令格式 LDR cond SBRd 加載指定地址上的數(shù)據(jù) 有符號字節(jié) 放入Rd中LDR cond SHRd 加載指定地址上的數(shù)據(jù) 有符號半字 放入Rd中LDR cond HRd 加載半字?jǐn)?shù)據(jù) 放入Rd中 即Rd最低16位有效 高16位清零STR cond HRd 存儲半字?jǐn)?shù)據(jù) 要存儲的數(shù)據(jù)在Rd 最16位有效這類LDR STR指令可加載有符號字節(jié) 加載有符號半字以及加載 存儲無符號半字 偏移量格式 尋址方式與加載 存儲字和無符號字節(jié)指令相同 3 2 1 3ARM存儲器訪問指令 10 說明 有符號位半字 字節(jié)加載是指用符號位擴(kuò)展到32位 無符號位半字加載是指零擴(kuò)展到32位 地址對齊 對半字傳送的地址必須是偶數(shù) 非半字對齊的半字加載將使Rd內(nèi)容不可靠 非半字對齊的半字存儲將使指令地址的2字節(jié)存儲內(nèi)容不可靠 應(yīng)用示例 LDR STR指令用于對內(nèi)存變量的訪問 內(nèi)存緩沖區(qū)數(shù)據(jù)的訪問 查表 外圍部件的控制操作等 若使用LDR指令加載數(shù)據(jù)到PC寄存器 則實現(xiàn)程序跳轉(zhuǎn)功能 這樣也就實現(xiàn)了程序散轉(zhuǎn) 3 2 1 3ARM存儲器訪問指令 11 LDR指令在異常向量表中的散轉(zhuǎn)應(yīng)用 在第2章中了解到每個異常都有自己的入口地址 那么在這些入口地址上放置的跳轉(zhuǎn)指令所組成的一段代碼 稱之為異常向量表 異常向量表的作用就是讓處理器在發(fā)生異常時能順利地找到對應(yīng)的服務(wù)程序 而異常向量表就是使用了LDR指令來實現(xiàn)程序散轉(zhuǎn)的 異常向量表的部分代碼如程序清單3 2所示 通過觀察LDR指令可以發(fā)現(xiàn) 它們使用的是 程序相對偏移 尋址方式 比如 復(fù)位異常入口處的指令 LDRPC ResetAddr 它是將程序標(biāo)號ResetAddr地址處存放的數(shù)據(jù)讀取到PC寄存器中 該地址上存放的是程序標(biāo)號ResetInit 它是復(fù)位異常服務(wù)程序的地址 因此一旦發(fā)生復(fù)位 處理器執(zhí)行復(fù)位異常入口處的指令 便可實現(xiàn)向復(fù)位服務(wù)程序的跳轉(zhuǎn)動作 更詳細(xì)的過程將在后續(xù)的內(nèi)容中陸續(xù)介紹 3 2 1 3ARM存儲器訪問指令 12 程序清單3 2LDR用于異常向量表實現(xiàn)程序散轉(zhuǎn) 3 2 1 3ARM存儲器訪問指令 13 LDR STR指令在變量操作中的應(yīng)用 在使用C語言時長定義一些全局變量 編譯器通常會將全局變量安排存放在存儲器中 所以在訪問該全局變量時就要用到LDR或STR指令 例如 在C語言下要實現(xiàn)兩個全局變量之間的參數(shù)傳遞 只需參見程序清單3 3代碼 程序清單3 3用C語言完成全局變量的參數(shù)傳遞該C代碼被編譯器編譯后便會生成如程序清單3 4所示的匯編代碼 代碼的前兩條LDR指令是偽指令 它用于將一個常數(shù)存放到寄存器中 LDR偽指令的詳細(xì)介紹參看 3 2 1 3ARM存儲器訪問指令 14 本小節(jié)的 ARM偽指令 它們在本程序中的用途是將全局變量OSPrioCur和OSPrioHighRdy的地址分別存放到R4和R5中 見圖3 4 在獲取到變量的地址后 第 句程序使用LDRB指令把OSPrioHighRdy變量的內(nèi)容取出 該指令的B后綴使它只讀取1字節(jié)數(shù)據(jù) 在第 句程序中 使用STRB指令把獲取到的OSPrioHighRdy變量內(nèi)容寫入到OSPrioCur變量中 整個代碼的執(zhí)行過程如程序清單3 4所示 程序清單3 4用LDR和STR指令實現(xiàn)全局變量的訪問 3 2 1 3ARM存儲器訪問指令 15 圖3 4全局變量訪問過程 3 2 1 3ARM存儲器訪問指令 16 2 LDM STM 多寄存器加載 存儲指令 指令格式 LDM cond Rn reglist STM cond Rn reglist 指令功能 多寄存器加載 存儲指令可以實現(xiàn)在一組寄存器和一塊連續(xù)的內(nèi)存單元之間傳輸數(shù)據(jù) LDM為加載多個寄存器 STM為存儲多個寄存器 允許一條指令傳送16個寄存器的任何子集或所有寄存器 指令說明 LDM和STM的主要用途是現(xiàn)場保護(hù) 數(shù)據(jù)復(fù)制 參數(shù)傳送等 其指令格式如圖3 5所示 圖3 5中 模式 有如下8種 前面4種用于數(shù)據(jù)塊的傳輸 后面4種是堆棧操作 IA 每次傳送后地址加4 IB 每次傳送前地址加4 DA 每次傳送后地址減4 DB 每次傳送前地址減4 3 2 1 3ARM存儲器訪問指令 17 FD 滿遞減堆棧 ED 空遞減堆棧 FA 滿遞增堆棧 EA 空遞增堆棧 圖3 5LDM和STM指令格式說明 3 2 1 3ARM存儲器訪問指令 18 注意事項 指令格式中的Rn寄存器為基址寄存器 它保存了所要操作存儲單元的起始地址 從該地址開始的一段連續(xù)的地址空間都是要進(jìn)行讀 寫的存儲單元 Rn不允許為R15 PC Rn的內(nèi)容是一個指針 在指令執(zhí)行前它指向起始地址 在指令執(zhí)行結(jié)束后有兩種選擇 一種是保持Rn的內(nèi)容前后不變化 其中 Rn無 后綴 如圖3 6 b 所示 另一種是讓Rn指向操作結(jié)束的地址 后綴 就是用于該功能的控制 如果加上 后綴 表示最后的地址寫回到Rn中 如圖3 6 c 所示 程序清單3 5帶 后綴的LDM指令 3 2 1 3ARM存儲器訪問指令 19 圖3 6LDM指令執(zhí)行前后寄存器狀態(tài) 3 2 1 3ARM存儲器訪問指令 20 寄存器列表reglist可包含多于一個寄存器或包含寄存器范圍 使用 分開 例如 R1 R2 R6 R9 寄存器就是由小到大排列 寄存器與內(nèi)存單元的對應(yīng)關(guān)系是 編號低的寄存器對應(yīng)于內(nèi)存中低地址單元 標(biāo)號高的寄存器對應(yīng)于內(nèi)存中的高地址單元 后綴不允許在用戶模式或系統(tǒng)模式下使用 若在LDM指令且寄存器列表中包含有PC時使用 那么除了正常的多寄存器傳送外 還會把SPSR也復(fù)制到CPSR中 這可用于異常處理返回 使用 后綴進(jìn)行數(shù)據(jù)傳送且寄存器列表不包含PC時 則加載 存儲的是用戶模式的寄存器 而不是當(dāng)前模式的寄存器 地址對齊 這些指令忽略地址的位 1 0 3 2 1 3ARM存儲器訪問指令 21 應(yīng)用示例 在進(jìn)行數(shù)據(jù)復(fù)制時 先設(shè)置好源數(shù)據(jù)指針和目標(biāo)指針 然后使用塊復(fù)制尋址指令LDMIA STMIA LDMIB STMIB LDMDA STMDA LDMDB STMDB進(jìn)行讀取和存儲 進(jìn)行堆棧操作時 要先設(shè)置堆棧指針 一般使用SP 然后使用堆棧尋址指令STMFD LDMFD STMED LDMED STMFA LDMFA和STMEA LDMEA實現(xiàn)堆棧操作 說明 上面提到的數(shù)據(jù)復(fù)制和堆棧操作的4種方式是可以互用的 比如 在使用STMFD時也可以使用LDMDB來替代 3 2 1 3ARM存儲器訪問指令 22 多寄存器傳送指令示意圖如圖3 7所示 其中R1為指令執(zhí)行前的基址寄存器 R1 則為指令執(zhí)行完后的基址寄存器 圖3 7多寄存器傳送指令示意圖 3 2 1 3ARM存儲器訪問指令 23 使用多寄存器傳送指令時 基址寄存器的地址是向上增長還是向下增長 地址是在加載 存儲數(shù)據(jù)之前還是之后增加 減少 其對應(yīng)關(guān)系如表3 3所列 表3 3多寄存器傳送指令映射 3 2 1 3ARM存儲器訪問指令 24 因為在實際應(yīng)用中通常使用C語言進(jìn)行程序編寫 所以此時的堆棧形式與編譯器有關(guān) 對于ADS工具自帶的C編譯器使用的是 滿遞減 的堆棧形式 如程序清單3 6所示 該指令是將寄存器R0 R7保存到堆棧之中 指令執(zhí)行前后的寄存器和存儲器內(nèi)容變化如圖3 8所示 通過仔細(xì)觀察可以發(fā)現(xiàn) 堆棧指針SP寄存器所指向的存儲器始終是保存有堆棧數(shù)據(jù)的 程序清單3 6滿遞減堆棧的壓棧操作 3 2 1 3ARM存儲器訪問指令 25 圖3 8使用STM壓棧指令的前后對比 3 2 1 3ARM存儲器訪問指令 26 與壓棧操作相對應(yīng)的出棧操作是通過LDM指令來實現(xiàn)的 需要特別注意 為了讓堆棧指針能正確移動 出棧和壓棧時的LDM指令的后綴必須都是一致的 比如程序清單3 6中使用的FD后綴 那么出棧時也同樣要使用FD后綴 如程序清單3 7和程序清單3 8所示 因為出棧操作常發(fā)生在函數(shù)返回時 所以通常在出棧的同時將之前入棧的LR寄存器內(nèi)容恢復(fù)到PC寄存器中 實現(xiàn)程序的返回 程序清單3 7使用LDM指令出棧程序清單3 8使用LDM指令出棧并恢復(fù)CPSR寄存器 3 2 1 3ARM存儲器訪問指令 27 仔細(xì)觀察程序清單3 7和程序清單3 8會發(fā)現(xiàn) 后者的指令上多了一個 符號 這個符號的功能是 如果操作寄存器組中存在PC寄存器 那么在恢復(fù)寄存器的同時將當(dāng)前模式下的SPSR寄存器內(nèi)容恢復(fù)到CPSR寄存器中 因此 程序清單3 7常用于子程序調(diào)用的出棧返回 而程序清單3 8常用于中斷服務(wù)程序的出棧返回 它們的使用效果如圖3 9所示 3 2 1 3ARM存儲器訪問指令 28 圖3 9使用LDM指令出棧操作 3 2 1 3ARM存儲器訪問指令 29 3 SWP 寄存器和存儲器交換指令 指令格式 SWP cond B Rd Rm Rn 指令功能 SWP指令用于將一個內(nèi)存單元 該單元地址放在寄存器Rn中 的內(nèi)容讀取到一個寄存器Rd中 同時將另一個寄存器Rm的內(nèi)容寫入到該內(nèi)存單元中 使用SWP可實現(xiàn)信號量操作 其中 B為可選后綴 若有B 則交換字節(jié) 否則交換32位字 Rd為數(shù)據(jù)從存儲器讀出后的目標(biāo)保存寄存器 Rm的數(shù)據(jù)存儲到存儲器中 若Rm與Rn相同 則寄存器與存儲器內(nèi)容進(jìn)行交換 Rn為要進(jìn)行數(shù)據(jù)交換的存儲器地址 Rn不能與Rd和Rm相同 3 2 1 3ARM存儲器訪問指令 30 應(yīng)用示例 3 2 1 4ARM數(shù)據(jù)處理指令 1 數(shù)據(jù)處理指令大致可分為3類 數(shù)據(jù)傳送指令 如MOV MVN 算術(shù)邏輯運(yùn)算指令 如ADD SUB AND 和比較指令 如CMP TST 見表3 4 其用法比較簡單 數(shù)據(jù)處理指令只能對寄存器的內(nèi)容進(jìn)行操作 所有ARM數(shù)據(jù)處理指令均可選擇使用S后綴 并影響狀態(tài)標(biāo)志 比較指令CMP CMN TST和TEQ不需要后綴S 它們會直接影響狀態(tài)標(biāo)志 3 2 1 4ARM數(shù)據(jù)處理指令 2 表3 4ARM數(shù)據(jù)處理指令 3 2 1 4ARM數(shù)據(jù)處理指令 3 CMP指令將寄存器Rn的值減去operand2的值 根據(jù)操作的結(jié)果更新CPSR中的相應(yīng)條件標(biāo)志位 以便后面的指令根據(jù)相應(yīng)的條件標(biāo)志來判斷是否執(zhí)行 指令格式 CMP cond Rn operand2應(yīng)用示例 CMP指令與SUBS指令的區(qū)別在于CMP指令不保存運(yùn)算結(jié)果 在進(jìn)行兩個數(shù)據(jù)的大小判斷時 常用CMP指令及相應(yīng)的條件碼來操作 程序清單3 9為使用CMP指令實現(xiàn)傳入?yún)?shù)的匹配操作 3 2 1 4ARM數(shù)據(jù)處理指令 4 程序清單3 9使用CMP指令實現(xiàn)數(shù)據(jù)比較 3 2 1 5乘法指令 ARM9TDMI S 具有32 32乘法指令 32 32乘加指令 32 32結(jié)果為64位的乘 乘加指令 ARM乘法指令見表3 5 由于其用法比較簡單 在此不再作詳細(xì)介紹 表3 5ARM乘法指令 3 2 1 6ARM分支指令 1 在ARM中有兩種方式可以實現(xiàn)程序的跳轉(zhuǎn) 一種是使用分支指令直接跳轉(zhuǎn) 另一種則是直接向PC寄存器賦值實現(xiàn)跳轉(zhuǎn) 分支指令有分支指令B 帶鏈接的分支指令BL 帶狀態(tài)切換的分支指令BX 見表3 6 由于其用法比較簡單 在此不再做詳細(xì)介紹 表3 6ARM分支指令 3 2 1 6ARM分支指令 2 1 B 分支指令 指令格式 B cond label指令編碼格式 signed immed 24 24位有符號立即數(shù) 偏移量 L 區(qū)別分支 L為0 或帶鏈接的分支指令 L為1 指令功能 B指令跳轉(zhuǎn)到指定的地址去執(zhí)行程序 3 2 1 6ARM分支指令 3 應(yīng)用示例 3 2 1 6ARM分支指令 4 2 BL 帶鏈接的分支指令 指令格式 BL cond label指令編碼格式 signed immed 24 24位有符號立即數(shù) 偏移量 L 區(qū)別分支 L為0 或帶鏈接的分支指令 L為1 指令功能 BL指令將下一條指令的地址復(fù)制到R14 即LR 鏈接寄存器中 然后跳轉(zhuǎn)到指令地址 運(yùn)行程序 3 2 1 6ARM分支指令 5 應(yīng)用示例 帶鏈接的分支指令BL限制在當(dāng)前指令的 32MB地址范圍內(nèi) BL指令用于子程序調(diào)用 3 2 1 6ARM分支指令 6 3 BX 帶狀態(tài)切換的分支指令 指令格式 BX cond Rm指令編碼格式 Rm 目標(biāo)地址寄存器 指令功能 BX指令跳轉(zhuǎn)到Rm指定的地址去執(zhí)行程序 若Rm的bit0為1 則跳轉(zhuǎn)時自動將CPSR中的標(biāo)志位T置位 即把目標(biāo)地址的代碼解釋為Thumb代碼 若Rm的bit0為0 則跳轉(zhuǎn)時自動將CPSR中的標(biāo)志位T復(fù)位 即把目標(biāo)地址的代碼解釋為ARM代碼 3 2 1 6ARM分支指令 7 應(yīng)用示例 3 2 1 7ARM雜項指令 1 ARM雜項指令見表3 7 表3 7ARM雜項指令 3 2 1 7ARM雜項指令 2 1 SWI 軟件中斷指令 指令格式 SWI cond immed 24指令編碼格式 Immed 24 24位立即數(shù) 為0 16777215之間的整數(shù) 常被用于參數(shù)傳遞 指令功能 SWI指令用于用于產(chǎn)生軟件中斷 從而實現(xiàn)從用戶模式到管理模式的變換 請參看第2章相關(guān)內(nèi)容 在切換時 CPSR寄存器內(nèi)容將保存到管理模式的SPSR中 同時程序跳轉(zhuǎn)到SWI異常向量入口處 在其他模式下也可使用SWI指令 處理器同樣會切換到管理模式 3 2 1 7ARM雜項指令 3 應(yīng)用示例 在2 7 10小節(jié)中 SWI常用于系統(tǒng)功能調(diào)用 在軟件中斷服務(wù)程序中根據(jù)程序傳遞的功能號來執(zhí)行對應(yīng)的服務(wù)程序 因此在使用軟件中斷時 功能號的傳遞和處理是一個很重要的步驟 通常使用以下兩種方法進(jìn)行功能號的傳遞 這兩種方法均由用戶軟件協(xié)定 指令中24位立即數(shù)指令了用戶請求的服務(wù)類型 參數(shù)通過通用寄存器傳遞 SWI異常中斷處理程序要通過讀取引起軟件中斷的SWI指令 以取得24位立即數(shù) 3 2 1 7ARM雜項指令 4 指令中的24位立即數(shù)被忽略 用戶請求的服務(wù)類型由寄存器R0的值決定 參數(shù)通過其他寄存器傳遞 在SWI異常中斷處理程序中 讀取SWI立即數(shù)的步驟為 首先 確定引起軟件中斷的SWI指令是ARM指令還是Thumb指令 這可通過對SPSR訪問得到 然后 取得該SWI指令的地址 這可通過訪問LR寄存器得到 最后 讀出指令 分解出立即數(shù) 如程序清單3 10所示 3 2 1 7ARM雜項指令 5 程序清單3 10讀取SWI立即數(shù) 3 2 1 7ARM雜項指令 6 2 MRS 讀狀態(tài)寄存器指令 指令格式 MRS cond Rd psr其中 Rd為目標(biāo)寄存器 Rd不允許為R15 psr為CPSR或SPSR 指令功能 在ARM處理器中 只有MRS指令可以將狀態(tài)寄存器CPSR或SPSR讀出到通用寄存器中 應(yīng)用示例 3 2 1 7ARM雜項指令 7 MRS指令讀取CPSR 可用來判斷ALU的狀態(tài)標(biāo)志 或IRQ FIQ中斷是否使能等 在異常處理程序中 讀SPSR可知道進(jìn)行異常前的處理器狀態(tài)等 MRS與MSR配合使用 實現(xiàn)CPSR或SPSR寄存器的讀 修改 寫操作 可用來進(jìn)行處理器模式切換 使能 禁止IRQ FIQ中斷等設(shè)置 如程序清單3 11 程序清單3 12所示 另外 進(jìn)程切換或使能異常中斷嵌套時 也需要使用MRS指令讀取SPSR狀態(tài)值 并保存起來 程序清單3 11使能IRQ中斷 3 2 1 7ARM雜項指令 8 程序清單3 12禁止IRQ中斷 3 2 1 7ARM雜項指令 9 3 MSR 寫狀態(tài)寄存器指令 指令格式 MSR cond psr fields immed 8rMSR cond psr fields Rm其中 psr為CPSR或SPSR fields為指定傳送的區(qū)域 fields可以是以下的一種或多種 字母必須為小寫 c 控制域屏蔽字節(jié) psr 7 0 x 擴(kuò)展域屏蔽字節(jié) psr 15 8 s 狀態(tài)域屏蔽字節(jié) psr 23 16 f 標(biāo)志域屏蔽字節(jié) psr 31 24 各個域在CPSR寄存器中的位置如圖3 10所示 3 2 1 7ARM雜項指令 10 圖3 10程序狀態(tài)寄存器的域的位置immed 8r為要傳送到狀態(tài)寄存器指定域的8位立即數(shù) Rm為要傳送到狀態(tài)寄存器指定域的數(shù)據(jù)的源寄存器 指令功能 在ARM處理器中 只有MSR指令可以直接設(shè)置狀態(tài)寄存器CPSR或SPSR 3 2 1 7ARM雜項指令 11 應(yīng)用示例 注意 只有在特權(quán)模式下才能修改狀態(tài)寄存器 程序中不能通過MSR指令直接修改CPSR中的T控制位來實現(xiàn)ARM狀態(tài) Thumb狀態(tài)的切換 必須使用BX指令完成處理器狀態(tài)的切換 因為BX指令屬分支指令 它會打斷流水線狀態(tài) 實現(xiàn)處理器狀態(tài)切換 MRS與MSR配合使用 實現(xiàn)CPSR或SPSR寄存器的讀 修改 寫操作 可用來進(jìn)行處理器模式切換 使能 禁止IRQ FIQ中斷等設(shè)置 如程序清單3 13所示 3 2 1 7ARM雜項指令 12 程序清單3 13堆棧指令初始化程序清單3 13中 MSRCPSR c 0Xd3 指令的操作結(jié)果入圖3 11所示 3 2 1 7ARM雜項指令 13 圖3 11向CPSR控制域?qū)懖僮鞯慕Y(jié)果 3 2 1 8ARM偽指令 1 ARM偽指令不是ARM指令集中的指令 只是為了編程方便 編譯器定義了偽指令 使用時可以像其他ARM指令一樣使用 但在編譯時這些指令將被等效的ARM指令代替 ARM常用的偽指令有4條 分別為ADR偽指令 ADRL偽指令 LDR偽指令 NOP偽指令 1 ADR 小范圍的地址讀取偽指令 指令格式 ADR cond register expr其中 register為加載的目標(biāo)寄存器 expr為地址表達(dá)式 當(dāng)?shù)刂分凳欠亲謱R時 取值范圍為 255 255字節(jié) 當(dāng)?shù)刂分凳亲謱R時 取值范圍為 1020 1020字節(jié) 對于基于PC相對偏移的地址值時 給定范圍是相對當(dāng)前指令地址后兩個字處 因為ARM9TDMI的流水線特性 3 2 1 8ARM偽指令 2 指令功能 ADR指令將基于PC相對偏移的地址值或基于寄存器相對偏移的地址值讀取到寄存器中 在匯編編譯源程序時 ADR偽指令被編譯器替換成一條合適的指令 通常 編譯器用一條ADD指令或SUB指令來實現(xiàn)該ADR偽指令的功能 若不能用一條指令實現(xiàn) 則產(chǎn)生錯誤 應(yīng)用示例 可以用ADR加載地址 實現(xiàn)查表 如程序清單3 14所示 3 2 1 8ARM偽指令 3 程序清單3 14小范圍地址的加載 3 2 1 8ARM偽指令 4 2 ADRL 中等范圍的地址讀取偽指令 指令格式 ADRL cond register expr其中 register為加載的目標(biāo)寄存器 expr為地址表達(dá)式 當(dāng)?shù)刂分凳欠亲謱R時 取值范圍為 64 64KB 當(dāng)?shù)刂分凳亲謱R時 取值范圍為 256 256KB 對于基于PC相對偏移的地址值時 給定范圍是相對當(dāng)前指令地址后兩個字處 因為ARM9TDMI的流水線特性 3 2 1 8ARM偽指令 5 指令功能 ADR指令將基于PC相對偏移的地址值或基于寄存器相對偏移的地址值讀取到寄存器中 比ADR偽指令讀取更大的地址范圍 在匯編編譯源程序時 ADRL偽指令被編譯器替換成兩條合適的指令 若不能用兩條指令實現(xiàn)ADRL偽指令功能 則產(chǎn)生錯誤 編譯失敗 應(yīng)用示例 3 2 1 8ARM偽指令 6 可以用ADRL加載地址 實現(xiàn)程序跳轉(zhuǎn) 如程序清單3 15所示 程序清單3 15中等范圍地址的加載 3 2 1 8ARM偽指令 7 3 LDR 大范圍的地址讀取偽指令 指令格式 LDR cond register expr label expr其中 register為加載的目標(biāo)寄存器 expr為32位立即數(shù) label expr是基于PC的地址表達(dá)式或外部表達(dá)式 指令功能 LDR偽指令用于加載32位的立即數(shù)或一個地址值到指定寄存器 在匯編編譯源程序時 LDR偽指令被編譯器替換成一條合適的指令 若加載的常數(shù)未超過MOV或MVN的范圍 則使用MOV或MVN指令代替該LDR偽指令 否則匯編器將常量放入文字池 并使用一條程序相對偏移的LDR加載指令從文字池讀出常量 3 2 1 8ARM偽指令 8 應(yīng)用示例 偽指令LDR常用于加載芯片外圍功能部件的寄存器 32位立即數(shù) 以實現(xiàn)各種控制操作 如程序清單3 16所示 3 2 1 8ARM偽指令 9 程序清單3 16加載32位立即數(shù)從PC到文字池的偏移量必須小于4KB 與ARM指令的LDR相比 偽指令的LDR的參數(shù)有 號 說明 若沒有使用LTORG聲明文字池 則匯編器會在程序末尾自動聲明 3 2 1 8ARM偽指令 10 4 NOP 空操作偽指令 指令格式 NOP指令功能 NOP偽指令在匯編時會被代替成ARM中的空操作 比如可能為 MOVR0 R0 指令等 NOP可用于延時操作 如程序清單3 17所示 程序清單3 17軟件延時 3 2 2Thumb指令集 Thumb指令集可以看作是ARM指令壓縮形式的子集 是針對代碼密度的問題而提出的 它具有16位的代碼密度 Thumb不是一個完整的體系結(jié)構(gòu) 不能指望處理器只執(zhí)行Thumb指令而不支持ARM指令集 因此 Thumb指令只需要支持通用功能 必要時可以借助完善的ARM指令集 比如 所有異常自動進(jìn)入ARM狀態(tài) 在編寫Thumb指令時 先要使用偽指令CODE16聲明 但是在ARM指令中要使用BX指令跳轉(zhuǎn)到Thumb指令 以切換處理器狀態(tài) 編寫ARM指令時 則可使用偽指令CODE32聲明 由ARM狀態(tài)切換到Thumb狀態(tài)的代碼 如程序清單3 18所示 程序清單3 18ARM到Thumb的狀態(tài)切換 程序首先在ARM狀態(tài)下使用 ADRR0 THUMB CODE 1 偽指令裝載THUMB CODE的地址 為了使R0的bit0為1 所以使用了 THUMB CODE 1 這樣使用BX即可把處理器狀態(tài)切換到Thumb狀態(tài) 所有ARM指令都是可以有條件執(zhí)行的 而Thumb指令僅有一條指令 分支指令B 具備條件執(zhí)行功能 ARM程序和Thumb程序可相互調(diào)用 相互之間的狀態(tài)切換幾乎為零 本章對Thumb指令僅做簡要介紹 3 2 2 1Thumb與ARM指令集的區(qū)別 1 Thumb指令集沒有協(xié)處理器指令 信號量指令以及訪問CPSR或SPSR的指令 沒有乘加指令及64位乘法指令等 并且指令的第二操作數(shù)受到限制 除了分支指令B有條件執(zhí)行功能外 其他指令均為無條件執(zhí)行 大多數(shù)Thumb數(shù)據(jù)處理指令采用2地址格式 Thumb指令集與ARM指令集的區(qū)別一般有如下4點 分支指令 程序相對轉(zhuǎn)移 特別是條件跳轉(zhuǎn)與ARM代碼下的跳轉(zhuǎn)相比 在范圍上有更多的限制 轉(zhuǎn)向子程序是無條件的轉(zhuǎn)移 數(shù)據(jù)處理指令 數(shù)據(jù)處理指令是對通用寄存器進(jìn)行操作 在大多數(shù)情況下 操作的結(jié)果須放入其中一個操作數(shù)寄存器中 而不是第3個寄存器中 數(shù)據(jù)處理操作比ARM狀態(tài)的更少 訪問R8 R15受到一定限制 除MOV和ADD指令訪問寄存器R8 R15外 其他數(shù)據(jù)處理指令總是更新CPSR中的ALU狀態(tài)標(biāo)志 訪問寄存器R8 3 2 2 1Thumb與ARM指令集的區(qū)別 2 R15的Thumb數(shù)據(jù)處理指令不能更新CPSR中的ALU狀態(tài)標(biāo)志 單寄存器加載和存儲指令 在Thumb狀態(tài)下 單寄存器加載和存儲指令只能訪問寄存器R0 R7 多寄存器加載和多寄存器存儲指令 LDM和STM指令可以將任何范圍為R0 R7的寄存器子集加載或存儲 PUSH和POP指令使用堆棧指針R13作為基址實現(xiàn)滿遞減堆棧 除R0 R7外 PUSH指令還可以存儲鏈接寄存器R14 并且POP指令可以加載程序計數(shù)器PC 3 2 2 2Thumb存儲器訪問指令 1 Thumb指令集的LDM和STM指令可以將任何范圍為R0 R7的寄存器子集加載或存儲 多寄存器加載和多寄存器存儲指令只有LDMIA STMIA指令 即每次傳送先加載數(shù)據(jù) 然后地址加4 對堆棧處理只能使用PUSH及POP指令 Thumb存儲器訪問指令見表3 8 Thumb存儲器訪問指令中 STR LDR STM LDM的使用方法與ARM指令集中相對應(yīng)的指令類似 不再詳細(xì)介紹 3 2 2 2Thumb存儲器訪問指令 2 表3 8Thumb存儲器訪問指令 3 2 2 3Thumb數(shù)據(jù)處理指令 1 大多
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 單位管理制度呈現(xiàn)大全【員工管理】十篇
- 《物業(yè)管理服務(wù)業(yè)》課件
- 三年級數(shù)學(xué)數(shù)學(xué)廣角課件
- 2024年農(nóng)業(yè)綜合開發(fā)和扶貧開發(fā)工作總結(jié)
- 2024年公司勞動社??粕习肽甑墓ぷ骺偨Y(jié)
- 空調(diào)機(jī)運(yùn)輸協(xié)議三篇
- 農(nóng)業(yè)產(chǎn)品銷售主管工作總結(jié)
- 通信科技前臺工作總結(jié)
- 家政服務(wù)前臺工作總結(jié)
- 機(jī)電裝備話務(wù)員工作總結(jié)
- 2024年小學(xué)五年級科學(xué)教學(xué)工作總結(jié)(2篇)
- GB/T 31900-2024機(jī)織兒童服裝
- 2023年首都機(jī)場集團(tuán)有限公司招聘考試真題
- 2024-2025學(xué)年冀教版數(shù)學(xué)五年級上冊期末測試卷(含答案)
- 2025年上半年浙江金華市永康市選調(diào)市紀(jì)檢監(jiān)察信息中心工作人員2人重點基礎(chǔ)提升(共500題)附帶答案詳解
- 美國制造業(yè)經(jīng)濟(jì)2024年度報告-2024-12-宏觀大勢
- 小區(qū)充電樁安全協(xié)議書范本(2篇)
- 2024年安徽省公務(wù)員錄用考試《行測》真題及答案解析
- 第二講 七十五載迎盛世 砥礪前行續(xù)華章2024年形勢與政策(課件)
- 車間班長年度述職報告
- 2024-2025學(xué)年高三年級上冊10月月考 生物試題
評論
0/150
提交評論