国产精品免费无遮挡无码永久视频-国产高潮视频在线观看-精品久久国产字幕高潮-国产精品99精品无码视亚

arm堆棧操作

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

尋址方式


說明


pop


=LDM


push


=STM


FA


遞增滿


LDMFA


LDMDA


STMFA


STMIB


FD


遞減滿


LDMFD


LDMIA


STMFD


STMDB


EA


遞增空


LDMEA


LDMDB


STMEA


STMIA


ED


遞減空


LDMED


LDMIB


STMED


STMDA

按照?qǐng)D表,可知 STMFD對(duì)應(yīng)的是STMDB,根據(jù)arm指令手冊(cè),可知STMDB入棧順序是(1方式)
而LDMFD對(duì)應(yīng)的是LDMIA,這樣這兩個(gè)操作就可以成功配對(duì):
以下是我在學(xué)習(xí)ARM指令中記錄的關(guān)于堆棧方面的知識(shí)

1、寄存器 R13 在 ARM 指令中常用作堆棧指針
  2、對(duì)于 R13 寄存器來(lái)說,它對(duì)應(yīng)6個(gè)不同的物理寄存器,其中的一個(gè)是用戶模式與系統(tǒng)模式共用,另外5個(gè)物理寄存器對(duì)應(yīng)于其他5種不同的運(yùn)行模式。采用以下的記號(hào)來(lái)區(qū)分不同的物理寄存器: R13_ 其中,mode為以下幾種模式之一:usr、fiq、irq、svc、abt、und。

  3、寄存器R13在ARM指令中常用作堆棧指針,但這只是一種習(xí)慣用法,用戶也可使用其他的寄存器作為堆棧指針。而在Thumb指令集中,某些指令強(qiáng)制性的要求使用R13作為堆棧指針。由于處理器的每種運(yùn)行模式均有自己獨(dú)立的物理寄存器R13,在用戶應(yīng)用程序的初始化部分,一般都要初始化每種模式下的R13,使其指向該運(yùn)行模式的棧空間,這樣,當(dāng)程序的運(yùn)行進(jìn)入異常模式時(shí),可以將需要保護(hù)的寄存器放入R13所指向的堆棧,而當(dāng)程序從異常模式返回時(shí),則從對(duì)應(yīng)的堆棧中恢復(fù),采用這種方式可以保證異常發(fā)生后程序的正常執(zhí)行。

  4、有四種類型的堆棧:

  堆棧是一種數(shù)據(jù)結(jié)構(gòu),按先進(jìn)后出(First In Last Out,F(xiàn)ILO)的方式工作,使用一個(gè)稱作堆棧指針的專用寄存器指示當(dāng)前的操作位置,堆棧指針總是指向棧頂。

  當(dāng)堆棧指針指向最后壓入堆棧的數(shù)據(jù)時(shí),稱為滿堆棧(Full Stack),而當(dāng)堆棧指針指向下一個(gè)將要放入數(shù)據(jù)的空位置時(shí),稱為空堆棧(Empty Stack)。

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

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

  ◎ Empty descending 空遞減堆棧堆棧首部是低(這里是不是錯(cuò)了,應(yīng)該是高地址吧)地址,堆棧向高地址增長(zhǎng)。棧指針總是指向下一個(gè)將要放入數(shù)據(jù)的空位置。

  ◎ Empty ascending 空遞增堆棧堆棧首部是高地址,堆棧向低地址增長(zhǎng)。棧指針總是指向下一個(gè)將要放入數(shù)據(jù)的空位置。

  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) 保護(hù)現(xiàn)場(chǎng)參數(shù),不影響PC,嵌匯編的時(shí)候?qū)χ暗拇鎱?shù)的寄存器R0~R12保存
STMFD r13!, {r0-r7,LR}
LDMFD r13!, {r0-r7,PC}
2)  ARM匯編中l(wèi)r(r14)寄存器的作用
lr(r14)的作用問題,這個(gè)lr一般來(lái)說有兩個(gè)作用:
1.當(dāng)使用bl或者blx跳轉(zhuǎn)到子過程的時(shí)候,r14保存了返回地址,可以在調(diào)用過程結(jié)尾恢復(fù)。
2.異常中斷發(fā)生時(shí),這個(gè)異常模式特定的物理R14被設(shè)置成該異常模式將要返回的地址。

另外注意pc,在調(diào)試的時(shí)候顯示的是當(dāng)前指令地址,而用mov lr,pc的時(shí)候lr保存的是此指令向后數(shù)兩條指令的地址,大家可以試一下用mov pc,pc,結(jié)果得到的是跳轉(zhuǎn)兩條指令,這個(gè)原因是由于arm的流水線造成的,預(yù)取兩條指令的結(jié)果.
3.我們看到的LR值是上一個(gè)子程序調(diào)用保存的子程序返回地址,這個(gè)LR是要賦給PC的。
  嵌入式匯編要手動(dòng)保存返回地址,進(jìn)行現(xiàn)場(chǎng)保護(hù)。
  PC記錄當(dāng)前運(yùn)行的地址。下一條回自己+4
  進(jìn)入子程序,LR才自動(dòng)更新為返回地址值,PC為程序運(yùn)行地址
ARM匯編嵌套子程序
幾個(gè)星期前閱讀了(加)Carl Hamacher、 Zvonko Vranesic、 Safwat Zaky編寫的《計(jì)算機(jī)組成》第五版中的ARM子程序調(diào)用的一些知識(shí),啟發(fā)很大,順便將它整理了一下并加入了自己的理解。
子程序
1 通過寄存器傳遞參數(shù)
BL指令通常用于調(diào)用一個(gè)子程序。它和B指令的區(qū)別在于它將返回地址裝載到R14中。由于子程序可能是嵌套的,因此LR的內(nèi)容必須保存在子程序所使用的堆棧中。
下面的例子使用寄存器傳遞參數(shù)。調(diào)用者通過寄存器R1和R2分別將數(shù)組的大小和數(shù)組的首地址傳遞給子程序;子程序利用寄存器R0將和傳遞給調(diào)用者。該子程序使用了寄存器R3,必須將它和LR推入堆棧。
調(diào)用程序
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過程調(diào)用標(biāo)準(zhǔn)),一般由調(diào)用者負(fù)責(zé)保存R0~R3,被調(diào)用者負(fù)責(zé)保存其他的寄存器以使調(diào)用返回后程序的狀態(tài)不被破壞。
2 通過堆棧傳遞參數(shù)
調(diào)用程序
LDR R0, POINTER
STR R0, [R13, #-4]! ;將數(shù)組首地址推入堆棧
LDR R0, N
STR R0, [R13, #-4]! ;將元素個(gè)數(shù)N推入堆棧
BL  LISTADD
LDR R0, [R13, #4] ;將元素和裝載到寄存器R0中
STR R0, SUM
ADD R13, R13, #8 ;恢復(fù)堆棧
子程序
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 嵌套子程序
當(dāng)子程序嵌套時(shí),堆棧是用于處理返回地址的最合適的數(shù)據(jù)結(jié)構(gòu)。當(dāng)調(diào)用子程序時(shí)在堆棧上建立了完整的堆棧結(jié)構(gòu)。應(yīng)當(dāng)注意當(dāng)前子程序的堆棧幀指針?biāo)赶虻目臻g中存儲(chǔ)的是調(diào)用當(dāng)前子程序的子程序的堆棧幀指針。調(diào)用者將子程序所需要的參數(shù)按照順序推入堆棧。子程序首先保存工作寄存器、調(diào)用者的堆棧幀指針以及返回地址,然后它計(jì)算自己的堆棧幀指針的值(ADD  FP, SP, #16),并利用這個(gè)堆棧幀指針從堆棧幀中獲取調(diào)用者傳遞給它的參數(shù)。在子程序完成它的任務(wù)之后,它也將返回值保存在堆棧中,此例保存在參數(shù)所在的內(nèi)存單元。調(diào)用者和被調(diào)用者必須約定好參數(shù)的傳遞順序和返回值保存位置。如果返回值比較多的話,調(diào)用者要為返回值預(yù)先在堆棧中保留合適的空間。
調(diào)用程序
2000 LDR   R0, PARAM2
STR   R0, [SP, #-4]! ;將參數(shù)推入堆棧
LDR   R0, PARAM1
STR  R0, [SP, #-4]!
BL   SUB1
2020 LDR  R0, [SP] ;保存SUB1的結(jié)果
STR  R0, RESULT
ADD  SP, SP, #8 ;恢復(fù)堆棧
子程序
2100 SUB1  STMFD  SP!, {R0-R3, FP,LR}
ADD  FP, SP, #16 ;計(jì)算幀指針
LDR  R0, [FP, #8] ;載入?yún)?shù)1
LDR  R1, [FP, #12] ;載入?yún)?shù)2
LDR  R2, PARAM3 ;載入?yún)?shù)3
STR  R2, [SP, #-4]! ;將參數(shù)3推入堆棧
BL  SUB2
2164 LDR  R2, [SP], #4 ;將SUB2的結(jié)果彈出并存儲(chǔ)在R2中,并遞增SP
STR  R3, [FP, #8] ;將結(jié)果推入堆棧
LDMFD  SP!, {R0-R3, FP, PC} ;恢復(fù)寄存器并返回
3000 SUB2  STMFD  SP!, {R0, R1, FP, LR}
ADD  FP, SP, #8 ;載入結(jié)構(gòu)指針
LDR  R0, [FP, #8] ;載入?yún)?shù)
STR  R1, [FP, #8] ;將結(jié)果推入堆棧
LDMFD  SP!, {R0, R1, FP, PC}


[R0] from SUB1


[R1] from SUB1


[FP] from SUB1


2164/返回地址


param3/SUB2的結(jié)果最后保存在這里


[R0] from main


[R1] from main


[R2] from main


[R3] from main


[FP] from main


2020/返回地址


param1/SUB1的結(jié)果最后保存在這里


param2


原棧頂



3 子程序編譯后都放在哪
嵌匯編子程序:會(huì)在編譯后統(tǒng)一放到一個(gè)地方 系統(tǒng)調(diào)用__main()庫(kù)函數(shù),
后再進(jìn)入main.c前的初始化C下面的堆棧命令前(這個(gè)堆棧是用來(lái)放置C里參數(shù)的)
   嵌匯編子程序:按定義順序放在堆棧前,而C語(yǔ)言子程序,放在初始化堆棧堆棧命令后。

本文地址:http://m.4huy16.com/thread-97735-1-1.html     【打印本頁(yè)】

本站部分文章為轉(zhuǎn)載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀點(diǎn)和對(duì)其真實(shí)性負(fù)責(zé);文章版權(quán)歸原作者及原出處所有,如涉及作品內(nèi)容、版權(quán)和其它問題,我們將根據(jù)著作權(quán)人的要求,第一時(shí)間更正或刪除。
您需要登錄后才可以發(fā)表評(píng)論 登錄 | 立即注冊(cè)

廠商推薦

  • Microchip視頻專區(qū)
  • “芯”光璀璨,鵬城共賞——2025 Microchip中國(guó)技術(shù)精英年會(huì)深圳站回顧
  • Microchip第22屆中國(guó)技術(shù)精英年會(huì)——采訪篇
  • 技術(shù)熱潮席卷三城,2025 Microchip中國(guó)技術(shù)精英年會(huì)圓滿收官!
  • Microchip第22屆中國(guó)技術(shù)精英年會(huì)上海首站開幕
  • 貿(mào)澤電子(Mouser)專區(qū)

相關(guān)視頻

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權(quán)所有   京ICP備16069177號(hào) | 京公網(wǎng)安備11010502021702
快速回復(fù) 返回頂部 返回列表