娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

歷史上的今天

今天是:2025年06月15日(星期日)

2021年06月15日 | ARM匯編語言 - 簡介 [一]

發布者:誰與爭鋒1 來源: eefocus關鍵字:ARM  匯編語言  礎知識 手機看文章 掃描二維碼
隨時隨地手機看文章

說明:本系列文章將主要以ARMv7和ARMv8架構為例,介紹ARM匯編語言的一些基礎知識。關于ARM匯編語言的學習,這里我要推薦一本書和一個網站,其中書是由宋巖翻譯的《Cortex-M3權威指南》,其文筆風趣幽默,引人入勝,網站則是azeria-labs。當然,ARM官方的Architecture Reference Manual更是重要的參考。


說起與系統結構相關的匯編語言,自然要先介紹該體系結構的寄存器組成。ARMv7相較于同為32位的x86,寄存器的數量要多一些,名稱和配置也不盡相同,但兩者還是有一個基本的對照關系:

ARMv7-A在設計之初,就有和之前系列的處理器(比如以ARM9系列為代表的ARMv5)兼容的七種處理器模式,后來在向ARMv8過渡的過程中,又增加了"MON"和"HYP"。


為了減少模式切換時的寄存器保存和恢復,同名寄存器在多種模式下各有一份,稱為bank register。某些模式會有自己專有的寄存器,比如FIQ就比IRQ多一些寄存器(R8到R12),這樣FIQ在進入和退出中斷的時候,所需要做的寄存器保存和恢復就可以減少,這也是它比IRQ更"Fast"的原因。

自從ARMv8出現以后,ARM的寄存器就全面進入了64位時代,通用寄存器的數量從13個(R0-R12)變成了30個(X0-X29) ,其名稱中的"R"也被"X"所取代了,但為了保持和32位系統的兼容性,每個ARMv8/ARM64通用寄存器都可被當做2個32位寄存器來使用,這樣的32位寄存器用"Wn"來表示。

ARMv8支持兩種執行狀態(execution state),分別是AArch64和AArch32,在AArch64狀態下執行的是A64指令集,在AArch32狀態下執行的是與ARMv7前向兼容的A32/T32指令集。

A64指令集看起來和前代的指令集差別不大,但其具有更高的編碼效率,別看它叫A64就以為它的指令長度是64位的,依然是32位,也就是4個字節。通常一條指令不會占據太多字節,而為了方便流水線的操作,ARM中指令的字節數通常是保持一致的(最多就是T32/Thumb-2這種2字節和4字節混合的指令),都設計成8個字節話的確挺浪費代碼空間。

ARMv8中的A32/T32指令集也不是和ARMv7中A32/T32一模一樣的,它做了一些改進和增強,如果你使用了這些強化的特性,當然可以獲得更好的性能,但是就不能和ARMv7完全兼容了。如果你希望同樣的一套匯編代碼在ARMv7和ARMv8中都能直接運行,就不能使用這部分額外的特性。


ARM雖說是RISC架構的,但RISC和CISC并不是涇渭分明的,雙方都在互相學習,取長補短。現在ARM支持的指令也是越來越多,本系列文章將僅介紹其中的一部分指令。

【數據傳送指令】

基礎的LDR/STR

在x86架構中,不管是寄存器之間,還是寄存器和內存之間,都可以使用MOV指令,并且直接操作內存單元上的數據是被允許的。


ARM架構中,寄存器間傳送數據的指令依然是MOV,比如"MOV Ra Rb" 就是把Rb里存放的數據傳送給Ra,但內存單元上的數據不允許被直接操作,而是必須先放到寄存器中,為此就有了把內存的內容傳送到寄存器的指令LDR(Load),以及把寄存器的內容傳送回內存的指令STR(Store)。

傳送的時候,內存單元的地址存放在一個寄存器中(比如R1),用[R1]表示,"[]"在這里就對應C語言里的"*",表示取地址里的內容。假設R1里存放的是0x200,內存中地址0x200處的內容是0x5,那么"ldr r0, [r1]"就是將0x5放入r0中。

通用寄存器的數量一共就那么多,直接用寄存器的值來獲取內存地址的數量實在太有限了,更多的時候,是通過寄存器的值(基址)加上一個偏移/索引(offset/index)來指向內存對應的單元,索引的大小可以由立即數提供,也可以由寄存器存儲的值提供:


STR  R0,[R1, #12]  // R0 --> [R1+12]

LDR  R4,[R5, R6]  // R4 <-- [R5+R6]


如果索引對基址的更改發生在數據傳輸之前,則稱為"預索引"(pre-index),傳輸前后寄存器R1的值都不會改變。

如果索引對基址的更改發生在數據傳輸之后(注意下圖"[]"位置的改變),則稱為"后索引"(post-index),傳輸后寄存器R1的內容將變為加上其原來的值加上索引后的值。"后索引"其實算是一種二合一的指令,比如"str r0, [r1], #12"就等同于"str r0, [r1]"加上"r1 = r1+12"。

好像缺了點什么,沒有既更改R1的值為R1+12,同時把*(R1+12)的值送入R0的?不急,這將在本文的后半段給出答案。


LDR和STR后面可以接一些后綴,比如"B", "H"和"W"分別表示從給定的內存地址取1個字節,2個字節和4個字節。

如果一次傳送的不是8個字節,那么64位的寄存器是填不滿的,為了保持負數的數值不變,這剩余的字節可能就需要進行符號位擴展(Signed),由后綴"S"表示,其配合"W"使用表示只進行低32位空余字節的擴展,配合"X"則表示進行整個64位的符號位擴展:

LDM/STM與三個問題

一個字節一個字節的傳送那是“螞蟻搬家”,如果要復制大批量的數據,效率實在不高,為此ARMv7還提供了用于批量傳輸的LDM和STM指令,"M"在這里代表Multiple。STM是把多個寄存器的值傳送到內存相鄰的位置,LDM反之。多個寄存器在ARM匯編語言中用"{}"圈起來,表示待傳送的寄存器列表。


比如"STM R0, {R4,R5}" 就表示將R4的值傳送到R0指向的內存單元,R5的值傳送到下一個內存單元。批量傳輸其實是存在一個方向問題的,為了區分下一個內存單元是在上一個單元的后面還是前面(地址更大還是更小),需要加上后綴"I"和"D"來分別表示"Increase"和"Decrease"。

還有一個問題,要將R5的值傳送到下一個內存單元,需要首先獲得這“下一個”內存單元的地址,這就涉及到地址的增減。假設R0的值是0,如果先增加"0"這個值(在32位系統中,一次增加的值是4),再傳送R4,那么就是[0x4]=R4, [0x8]=R5;如果是傳送完R4后再增加"0"這個值,那么就是[0x0]=R4, [0x4]=R5。所以還需要加上后綴"A"和"B"來分別表示"After"(傳送后增加)和"Before"(傳送前增加)。


因此,LDM/STM家族一共有"IA", "IB", "DA"和"DB"四個變種(variant),"LDM"和"STM"什么后綴都不接也可以直接使用,但它其實包含一個隱式規則,即默認為"IA",也就是說"LDM"和"STM"其實分別等同于"LDMIA"和"STMIA"。

在函數調用中,進入子函數的時候要用"PUSH"指令,把存儲在CPU寄存器中的局部變量/上下文保存到內存的棧中,退出子函數的時候要用"POP"指令,將棧中保存的內容恢復到對應的寄存器中,因為棧通常是自頂向下生長的,所以"PUSH"和"POP"其實可以分別用"STMDB"和"LDMIA"來替代。


STR  R0,[R1, #12]  // R0 --> [R1+12]

LDR  R4,[R5, R6]  // R4 <-- [R5+R6]


這里出現了一個"!"符號,那就是我們要解決的第三個問題:在增加/減少"SP"表示的這個數值(比如前面假設的"0")的時候,"SP"本身存儲的內容是否跟著一起變化?加上"!"就表示在傳送過程中"SP"會自增/自減,傳送完成后"SP"的值已經不再是傳送前的那個值了,不加"!"就是在傳送前后保持"SP"的內容不變。"SP"作為stack pointer,在入棧和出棧的時候自然是要移動的,所以這里用了"!"。


"!"是表示寄存器自增/自減的,所以它并不局限于配合LDM/STM使用,如果它用在STR指令中,比如"str r0, [r1, #12]!",就相當于"str r0 [r1, #12]"加上"r1 = r1+12",這也解決了本文前半段介紹LDR/STR指令時留下的那個問題。

新一代的LDP/STP

在ARMv8中,LDM/STM被新一代的指令LDP(Load Pair)和STP(Store Pair)所取代了,LDM/STM對寄存器列表里包含的寄存器數量并沒有什么限制,而LDP/STP要求和內存之間傳送數據的寄存器不超過2個。因為"PUSH"和"POP"完全可以用LDM/STM表示,所以他倆也被一并干掉了。兩代指令的對應關系大概是這樣的:


小結一下,本文主要介紹了ARMv7和ARMv8的數據傳送指令,并在其中穿插了ARM匯編語言中"[]", "{}", "!"符號的含義和用法。下文將介紹移位、序轉和位操作等數據處理指令。

關鍵字:ARM  匯編語言  礎知識 引用地址:ARM匯編語言 - 簡介 [一]

上一篇:ARM匯編語言 - 簡介 [二]
下一篇:ARM匯編語言入門(七)

推薦閱讀

習慣了調程序遇到問題就在網上各種搜羅,常常能從大牛的記錄或者回復中得到啟發,沒想到有一天自己也開始寫博客記錄下學習的點滴。學習STM32的這一個月頗有點閉門造車的意思,因為周圍沒有學習這個開發板的朋友,遇到問題要么遠程求助要么自己琢磨,感覺略苦逼,也容易造成不自信。。。最近一直斷斷續續得學習STM32里的中斷實驗,遇到了很多問題,今天總算...
CES Asia開幕之前,我建議同事把報道的主題改為“回歸”。那是因為從開幕之前透露出的廠商和技術名單上,都能看到一股空前的“實用”味道。而當我站在CES Asia的會場之中時,那種變革的味道就更為明顯。囿于車市走低的大環境,再加上新勢力競爭的緊迫感,即便汽車已經成為CES Asia(乃至CES本體)最大的設展單元,哪些公司參展,展示哪些技術,都成為頗...
一張“不得不用”的5G手機卡讓家住北京的張先生苦惱不已。近日,張先生向北京商報記者投訴,他辦理了北京聯通的一款“5G+寬帶”融合套餐,并按期足額繳納了套餐月租,但因他未使用套餐內的5G手機卡,便被北京聯通切斷了寬帶。對于張先生的遭遇,北京聯通方面認為自己嚴格按照協議辦事,并無過錯。不過,有律師認為,北京聯通的協議可能涉嫌霸王條款。專家...
今年年初,針對新能源汽車新一年的市場表現,不少業內人士及行業機構給出了樂觀的預測,不過,目標也只是定在了180萬輛左右。然而幾個月過去,新能源汽車市場的超預期表現,讓不少行業人士對其今年的表現又有了新的看法,一些業內人士直接將銷量目標拉高到了200萬輛以上,全國乘用車市場信息聯席會(以下簡稱“乘聯會”)甚至預判,今年新能源汽車銷量會達...

史海拾趣

問答坊 | AI 解惑

請大家幫忙說下DA轉換器后面的電路一般接什么?

請大家幫忙說下DA轉換器后面的電路一般接什么?我用的是TLV5619,12路數字量轉模擬量,出來的模擬信號是不是要加什么射隨器、采樣保持器什么的?麻煩說詳細點,謝謝…

查看全部問答∨

2008年山東省競賽優秀論文選集

本帖最后由 paulhyde 于 2014-9-15 09:15 編輯 這是2008年山東省的競賽報告,用得上的可下載去看看。  …

查看全部問答∨

求助各位大哥

USB轉/RS232/紅外收發?哪位路過的大俠指點下啊:\'( [ 本帖最后由 ttdatazx 于 2009-10-19 09:03 編輯 ]…

查看全部問答∨

LED驅動

各位大哥大姐,教小弟怎么學習LED驅動!!!!!!!!謝啦!…

查看全部問答∨

求助:車載多媒體Gps升級

首先申明一下,我不是搞開發的也不是程序員,是一個用戶,發帖的目的就是因為我總的車載導航最大只支持2G的SD卡,機器也沒有usb口,是和車載dvd一體式的設計,用過網上的一些辦法,將SDHC的驅動考到windows目錄,將注冊表文件合并,可是這樣一重新 ...…

查看全部問答∨

為什么光驅無法識別DVD空白光盤

新買的DVD空白光盤,光驅卻無法識別,顯示“請插入光盤”,我的電腦光驅是DVD/CD-RW驅動器,按說應該支持DVD才對呀?…

查看全部問答∨

菜鳥求助

求推薦10位、160k之上的常用AD轉換芯片…

查看全部問答∨

EDA技術實用教程

EDA技術實用教程 [ 本帖最后由 白丁 于 2013-7-18 21:39 編輯 ]…

查看全部問答∨

初學者,一小段程序求解~

一個工程里的一個部分,程序中出現如下表述: BEGIN         HS_ein                 = Bereit # Betrieb; --on all the time, except for AUS or FEHLER or LADEN     ...…

查看全部問答∨

藍牙產品+陶瓷天線+應用

目前很多藍牙產品越來越精小,對于板上空間來講就要處處考慮了,PCB天線是最常見的,但是比較占用大的PCB面積,陶瓷天線開始應用了。 有誰用過陶瓷天線的?可以分享一下應用效果么?一致性如何?…

查看全部問答∨
小廣播
設計資源 培訓 開發板 精華推薦

最新單片機文章
何立民專欄 單片機及嵌入式寶典

北京航空航天大學教授,20余年來致力于單片機與嵌入式系統推廣工作。

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 上思县| 水城县| 旌德县| 汉沽区| 马公市| 新乐市| 宾阳县| 奎屯市| 右玉县| 漳州市| 汕尾市| 华阴市| 兴和县| 江阴市| 隆安县| 成武县| 永胜县| 香格里拉县| 治多县| 镇江市| 临海市| 云霄县| 和顺县| 伊金霍洛旗| 黄骅市| 洮南市| 乌拉特后旗| 滦平县| 江孜县| 竹溪县| 诸城市| 贵州省| 德昌县| 铜梁县| 镇平县| 南平市| 临夏县| 连州市| 华安县| 昭苏县| 苍南县|