国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

arm堆棧操作

發布時間:2012-9-17 18:48    發布者:a861388037
關鍵詞: arm
arm堆棧操作
arm堆棧的組織結構是 滿棧降 的形式,滿棧即sp是要停留在最后一個進棧元素,降:就是堆棧的增長方向是從高地址向低地址發展。
arm對于堆棧的操作一般采用 LDMFD(pop)和STMFD (push) 兩個命令。
以前困惑的就是STMFD 命令 對于操作數 是按照什么順序壓棧的
比如:STMFD sp!{R0-R5,LR} 進棧順序是:
高地址(1方式)
LR
R5
R4
```````
R0   <-sp
低地址
還是:
高地址(2方式)
R0
R1
```
R5
LR <-sp
低地址
現在通過下表,可以輕松的解決這個問題:

尋址方式


說明


pop


=LDM


push


=STM


FA


遞增滿


LDMFA


LDMDA


STMFA


STMIB


FD


遞減滿


LDMFD


LDMIA


STMFD


STMDB


EA


遞增空


LDMEA


LDMDB


STMEA


STMIA


ED


遞減空


LDMED


LDMIB


STMED


STMDA

按照圖表,可知 STMFD對應的是STMDB,根據arm指令手冊,可知STMDB入棧順序是(1方式)
而LDMFD對應的是LDMIA,這樣這兩個操作就可以成功配對:
以下是我在學習ARM指令中記錄的關于堆棧方面的知識

1、寄存器 R13 在 ARM 指令中常用作堆棧指針
  2、對于 R13 寄存器來說,它對應6個不同的物理寄存器,其中的一個是用戶模式與系統模式共用,另外5個物理寄存器對應于其他5種不同的運行模式。采用以下的記號來區分不同的物理寄存器: R13_ 其中,mode為以下幾種模式之一:usr、fiq、irq、svc、abt、und。

  3、寄存器R13在ARM指令中常用作堆棧指針,但這只是一種習慣用法,用戶也可使用其他的寄存器作為堆棧指針。而在Thumb指令集中,某些指令強制性的要求使用R13作為堆棧指針。由于處理器的每種運行模式均有自己獨立的物理寄存器R13,在用戶應用程序的初始化部分,一般都要初始化每種模式下的R13,使其指向該運行模式的?臻g,這樣,當程序的運行進入異常模式時,可以將需要保護的寄存器放入R13所指向的堆棧,而當程序從異常模式返回時,則從對應的堆棧中恢復,采用這種方式可以保證異常發生后程序的正常執行。

  4、有四種類型的堆棧:

  堆棧是一種數據結構,按先進后出(First In Last Out,FILO)的方式工作,使用一個稱作堆棧指針的專用寄存器指示當前的操作位置,堆棧指針總是指向棧頂。

  當堆棧指針指向最后壓入堆棧的數據時,稱為滿堆棧(Full Stack),而當堆棧指針指向下一個將要放入數據的空位置時,稱為空堆棧(Empty Stack)。

  同時,根據堆棧的生成方式,又可以分為遞增堆棧(Ascending Stack)和遞減堆棧(DecendingStack),當堆棧由低地址向高地址生成時,稱為遞增堆棧,當堆棧由高地址向低地址生成時,稱為遞減堆棧。這樣就有四種類型的堆棧工作方式,ARM 微處理器支持這四種類型的堆棧工作方式,即:
       ◎ Full descending 滿遞減堆棧堆棧首部是高地址,堆棧向低地址增長。棧指針總是指向堆棧最后一個元素(最后一個元素是最后壓入的數據)。 ARM-Thumb過程調用標準和ARMThumb C/C++ 編譯器總是使用Full descending 類型堆棧。<這是什么原因呢?>

  ◎ Full ascending 滿遞增堆棧堆棧首部是低地址,堆棧向高地址增長。棧指針總是指向堆棧最后一個元素(最后一個元素是最后壓入的數據)。

  ◎ Empty descending 空遞減堆棧堆棧首部是低(這里是不是錯了,應該是高地址吧)地址,堆棧向高地址增長。棧指針總是指向下一個將要放入數據的空位置。

  ◎ Empty ascending 空遞增堆棧堆棧首部是高地址,堆棧向低地址增長。棧指針總是指向下一個將要放入數據的空位置。

  5、操作堆棧的匯編指令堆棧類型 入棧指令 出棧指令 Full descending STMFD (STMDB) LDMFD (LDMIA) Full ascending STMFA (STMIB) LDMFA (LDMDA) Empty descending STMED (STMDA) LDMED (LDMIB) Empty ascending STMEA (STMIA) LDMEA (LDMDB)

  例子: STMFD r13!, {r0-r5} ; Push onto a Full Descending Stack LDMFD r13!, {r0-r5} ; Pop from a Full Descending Stack.
例子
1) 保護現場參數,不影響PC,嵌匯編的時候對之前的存參數的寄存器R0~R12保存
STMFD r13!, {r0-r7,LR}
LDMFD r13!, {r0-r7,PC}
2)  ARM匯編中lr(r14)寄存器的作用
lr(r14)的作用問題,這個lr一般來說有兩個作用:
1.當使用bl或者blx跳轉到子過程的時候,r14保存了返回地址,可以在調用過程結尾恢復。
2.異常中斷發生時,這個異常模式特定的物理R14被設置成該異常模式將要返回的地址。

另外注意pc,在調試的時候顯示的是當前指令地址,而用mov lr,pc的時候lr保存的是此指令向后數兩條指令的地址,大家可以試一下用mov pc,pc,結果得到的是跳轉兩條指令,這個原因是由于arm的流水線造成的,預取兩條指令的結果.
3.我們看到的LR值是上一個子程序調用保存的子程序返回地址,這個LR是要賦給PC的。
  嵌入式匯編要手動保存返回地址,進行現場保護。
  PC記錄當前運行的地址。下一條回自己+4
  進入子程序,LR才自動更新為返回地址值,PC為程序運行地址
ARM匯編嵌套子程序
幾個星期前閱讀了(加)Carl Hamacher、 Zvonko Vranesic、 Safwat Zaky編寫的《計算機組成》第五版中的ARM子程序調用的一些知識,啟發很大,順便將它整理了一下并加入了自己的理解。
子程序
1 通過寄存器傳遞參數
BL指令通常用于調用一個子程序。它和B指令的區別在于它將返回地址裝載到R14中。由于子程序可能是嵌套的,因此LR的內容必須保存在子程序所使用的堆棧中。
下面的例子使用寄存器傳遞參數。調用者通過寄存器R1和R2分別將數組的大小和數組的首地址傳遞給子程序;子程序利用寄存器R0將和傳遞給調用者。該子程序使用了寄存器R3,必須將它和LR推入堆棧。
調用程序
LDR R1, N
LDR R2, POINTER
BL  LISTADD
STR R0, SUM
子程序
LISTADD  STMFD  R13!, {R3, R14}
MOV  R0, #0
LOOP LDR  R3, [R2], #4
ADD  R0, R0, R3
SUBS  R1, R1, #1
BGT  LOOP
LDMFD R13!, {R3, R15}
注:這里并沒有遵守APCS(ARM過程調用標準),一般由調用者負責保存R0~R3,被調用者負責保存其他的寄存器以使調用返回后程序的狀態不被破壞。
2 通過堆棧傳遞參數
調用程序
LDR R0, POINTER
STR R0, [R13, #-4]! ;將數組首地址推入堆棧
LDR R0, N
STR R0, [R13, #-4]! ;將元素個數N推入堆棧
BL  LISTADD
LDR R0, [R13, #4] ;將元素和裝載到寄存器R0中
STR R0, SUM
ADD R13, R13, #8 ;恢復堆棧
子程序
LISTADD  STMFD  R13!, {R0-R3, R14}
LDR  R1, [R13, #20]
LDR  R2, [R13, #24]
MOV  R0, #0
LOOP LDR  R3, [R2], #4
ADD  R0, R0, R3
SUBS  R1, R1, #1
BGT  LOOP
STR R0, [R13,#24] ;把和推入堆棧的最深處
LDMFD R13!, {R0-R3, R15}

[R0]


[R1]


[R2]


[R3]


返回地址


N


POINTER/SUM

3 嵌套子程序
當子程序嵌套時,堆棧是用于處理返回地址的最合適的數據結構。當調用子程序時在堆棧上建立了完整的堆棧結構。應當注意當前子程序的堆棧幀指針所指向的空間中存儲的是調用當前子程序的子程序的堆棧幀指針。調用者將子程序所需要的參數按照順序推入堆棧。子程序首先保存工作寄存器、調用者的堆棧幀指針以及返回地址,然后它計算自己的堆棧幀指針的值(ADD  FP, SP, #16),并利用這個堆棧幀指針從堆棧幀中獲取調用者傳遞給它的參數。在子程序完成它的任務之后,它也將返回值保存在堆棧中,此例保存在參數所在的內存單元。調用者和被調用者必須約定好參數的傳遞順序和返回值保存位置。如果返回值比較多的話,調用者要為返回值預先在堆棧中保留合適的空間。
調用程序
2000 LDR   R0, PARAM2
STR   R0, [SP, #-4]! ;將參數推入堆棧
LDR   R0, PARAM1
STR  R0, [SP, #-4]!
BL   SUB1
2020 LDR  R0, [SP] ;保存SUB1的結果
STR  R0, RESULT
ADD  SP, SP, #8 ;恢復堆棧
子程序
2100 SUB1  STMFD  SP!, {R0-R3, FP,LR}
ADD  FP, SP, #16 ;計算幀指針
LDR  R0, [FP, #8] ;載入參數1
LDR  R1, [FP, #12] ;載入參數2
LDR  R2, PARAM3 ;載入參數3
STR  R2, [SP, #-4]! ;將參數3推入堆棧
BL  SUB2
2164 LDR  R2, [SP], #4 ;將SUB2的結果彈出并存儲在R2中,并遞增SP
STR  R3, [FP, #8] ;將結果推入堆棧
LDMFD  SP!, {R0-R3, FP, PC} ;恢復寄存器并返回
3000 SUB2  STMFD  SP!, {R0, R1, FP, LR}
ADD  FP, SP, #8 ;載入結構指針
LDR  R0, [FP, #8] ;載入參數
STR  R1, [FP, #8] ;將結果推入堆棧
LDMFD  SP!, {R0, R1, FP, PC}


[R0] from SUB1


[R1] from SUB1


[FP] from SUB1


2164/返回地址


param3/SUB2的結果最后保存在這里


[R0] from main


[R1] from main


[R2] from main


[R3] from main


[FP] from main


2020/返回地址


param1/SUB1的結果最后保存在這里


param2


原棧頂



3 子程序編譯后都放在哪
嵌匯編子程序:會在編譯后統一放到一個地方 系統調用__main()庫函數,
后再進入main.c前的初始化C下面的堆棧命令前(這個堆棧是用來放置C里參數的)
   嵌匯編子程序:按定義順序放在堆棧前,而C語言子程序,放在初始化堆棧堆棧命令后。

本文地址:http://m.qingdxww.cn/thread-97735-1-1.html     【打印本頁】

本站部分文章為轉載或網友發布,目的在于傳遞和分享信息,并不代表本網贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問題,我們將根據著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發表評論 登錄 | 立即注冊

廠商推薦

  • Microchip視頻專區
  • 使用SAM-IoT Wx v2開發板演示AWS IoT Core應用程序
  • 使用Harmony3加速TCP/IP應用的開發培訓教程
  • 集成高級模擬外設的PIC18F-Q71家族介紹培訓教程
  • 探索PIC16F13145 MCU系列——快速概覽
  • 貿澤電子(Mouser)專區

相關視頻

關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯系我們
電子工程網 © 版權所有   京ICP備16069177號 | 京公網安備11010502021702
快速回復 返回頂部 返回列表
主站蜘蛛池模板: 伊人久久精品AV无码一区| 亚洲日本va中文字幕| 手机看片日韩欧美| 色综合天天综合网国产成人网| 亚洲乱人伦精品图片| 成年人视频在线免费播放| 日韩爽爽影院在线播放| 无遮挡很爽很污很黄很色的网站| 热re99久久国产精品| 最近更新免费中文字幕大全| 一本大道香蕉在线 观看| 国产精品18久久久久网站| 热思思| 日日欧美| 日韩毛片大全免费高清| 中文字幕在线色| 97在线播放| 免费观看视频成人国产| 欧美一级成人免费大片| 日b视频在线观看| 中文字幕视频不卡| 99麻豆精品国产人妻无码| 色戒2小时38分在线观看| 亚洲第一页在线播放| 日本天堂在线视频| 无限国产资源| www红色一片| 小学生偷拍妈妈视频遭性教育 | 大学生第一次破女在线观看| 善良的女房东味道2在线观看| 欧美性久久| 伊人365影院| 在线看免费视频| 欧美日韩亚洲一区视频二区| 欧美日韩一区二区在线| 亚洲不卡视频| 综合天堂| 欧美精品XXXXBBBB| 一级毛片高清免费播放| 性xxxxx| 一二三四视频高清观看在线播放|