在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            入門級ARM匯編指令

            作者: 時(shí)間:2016-11-09 來源:網(wǎng)絡(luò) 收藏
            無論是體系結(jié)構(gòu)還是指令集,大家或多或少都應(yīng)該對X86匯編有些了解,而對于嵌入式領(lǐng)域已被廣泛采用的ARM 處理器,了解的可能并不多。如果你有興趣從事嵌入式方面的開發(fā),那么了解一些RISC 體系結(jié)構(gòu)和ARM匯編的知識還是有必要的。這里,我們找出了這兩種體系結(jié)構(gòu)最明顯的不同之處,并對此進(jìn)行介紹,讓大家對于RISC體系結(jié)構(gòu)的匯編有一個基本的了解。首先,我們就來看一看基于RISC的ARM的體系結(jié)構(gòu)。

            基于RISC 的ARM CPU
            ARM是一種RISC體系結(jié)構(gòu)的處理器芯片。和傳統(tǒng)的CISC體系結(jié)構(gòu)不同,RISC 有以下的幾個特點(diǎn):
            ◆ 簡潔的指令集——為了保證CPU可以在高時(shí)鐘頻率下單周期執(zhí)行指令,RISC指令集只提供很有限的操作(例如add,sub,mul等),而復(fù)雜的操作都需要由這些簡單的指令來組合進(jìn)行模擬。并且,每一條指令不僅執(zhí)行時(shí)間固定,其指令長度也是固定的,這樣,在譯碼階段就可以對下一條指令進(jìn)行預(yù)取。
            ◆ Load-Store 結(jié)構(gòu)——這個應(yīng)該是RISC 設(shè)計(jì)中比較有特點(diǎn)的一部分。在RISC 中,CPU并不會對內(nèi)存中的數(shù)據(jù)進(jìn)行操作,所有的計(jì)算都要求在寄存器中完成。而寄存器和內(nèi)存的通信則由單獨(dú)的指令來完成。而在CSIC中,CPU是可以直接對內(nèi)存進(jìn)行操作的,這也是一個比較特別的地方。
            ◆ 更多的寄存器——和CISC 相比,基于RISC的處理器有更多的通用寄存器可以使用,且每個寄存器都可以進(jìn)行數(shù)據(jù)存儲或者尋址。
            當(dāng)然,作為RISC 領(lǐng)域最成功的處理器,ARM也遵從上面的特點(diǎn)。這里,我們不妨來看一看在user 模式下,ARM處理器的體系結(jié)構(gòu),這對于我們了解其匯編語言是有好處的。而其它模式下只是有一些寄存器分組略有不同,大家可以在ARM的手冊上查到。這里要說明的是,盡管ARM處理器也支持16位指令,不過在下文中,我們都假定ARM處理器在32 位模式下工作。


            圖1:user模式下ARM處理器體系結(jié)構(gòu)
            從圖1中我們看到,在user 模式下,ARM CPU 有16個數(shù)據(jù)寄存器,被命名為r0~r15(這個要比x86的多一些)。r13~r15有特殊用途,其中:
            ◆ r13 - 指向當(dāng)前棧頂,相當(dāng)于x86的esp,這個東西在匯編指令中要用sp 表示
            ◆ r14 - 稱作鏈接寄存器,指向函數(shù)的返回地址。用lr表示,這和x86將返回地址保存在棧中是不同的
            ◆ r15 - 類似于x86的eip,其值等于當(dāng)前正在執(zhí)行的指令的地址+8(因?yàn)樵谌≈泛蛨?zhí)行之間多了一個譯碼的階段),這個用pc表示
            另外,ARM處理器還有一個名為cspr的寄存器,用來監(jiān)視和控制內(nèi)部操作,這點(diǎn)和x86 的狀態(tài)寄存器是類似的。具體的內(nèi)容就用到再說了。

            本文引用地址:http://www.biyoush.com/article/201611/317878.htm

            ARM 指令集
            ARM處理器可以支持3種指令集——ARM,Thumb和Jazelle。
            采用那種指令集,由cspr中的標(biāo)志位來決定。大體說來:
            ◆ ARM——這是ARM自身的32 位指令集
            ◆ Thumb ——這是一個全16 位的指令集,在16 位外部數(shù)據(jù)總線寬度下,這個指令集的效率要比32 位的ARM指令高一些。
            ◆ Jazelle ——這是一個8位指令集,用來加速Java字節(jié)碼的執(zhí)行
            整個ARM指令集由數(shù)據(jù)處理指令、分支指令、Load-Store指令、程序中斷指令和一些系統(tǒng)控制指令構(gòu)成,除了Load-Store指令外,其他部分和x86指令集是比較類似的。但和x86相比,ARM指令最顯著的特點(diǎn)它們都是32-bit 定長的。另外,由于arm是基于RISC指令集的,所以CPU只處理在寄存器中的數(shù)據(jù)并通過獨(dú)立的load-store指令在內(nèi)存和寄存器之間進(jìn)行數(shù)據(jù)的傳遞。
            在使用方面,ARM指令的格式也要比Intel的復(fù)雜些。一般說來,一條ARM指令有如下的形式:
            {S} [Rd], [Rn], [Rm]
            其中:
            * {S} —— 加上這個后綴的指令會更新cpsr 寄存器
            * [Rd] —— 目的寄存器
            * [Rn]/[Rm] —— 源寄存器
            一般來說,arm 指令有3個操作數(shù),其中Rm寄存器在執(zhí)行指令前可以進(jìn)入桶形移位器進(jìn)行移位操作,而Rn則會直接進(jìn)入ALU 單元。如果一條arm 指令只有2 個操作數(shù),那么源寄存器按照Rm 來處理。例如,一條加法指令:
            add r0, r1, #1
            就會把r1+1的結(jié)果存放到r0中。
            在熟悉了基本的匯編格式后,讀者就可以自行去查詢基本的ARM匯編指令了,下面,我們找出ARM中比較有特色部分——Load-Store指令結(jié)構(gòu),它是CPU 和內(nèi)存進(jìn)行通信的一個重要媒介。

            Load-Store 指令體系
            由于ARM CPU并不直接處理內(nèi)存中的數(shù)據(jù),這個指令體系就擔(dān)起了在寄存器和內(nèi)存之間交換數(shù)據(jù)的重要媒介。它要比x86 的內(nèi)存訪問機(jī)制復(fù)雜一些。該指令體系分成3 類:
            ◆ 單寄存器傳輸(這是與x86 最為相像的)
            ◆ 多寄存器傳輸
            ◆ 交換指令

            單寄存器傳輸
            先看第一個,很簡單:把單一的數(shù)據(jù)傳入(LDR) 或傳出(STR)寄存器,對內(nèi)存的訪問可以是DWORD(32-bit), WORD(16-bit)和BYTE(8-bit)。指令的格式如下:
            DWORD:
            Rd, addressing1
            WORD:
            H Rd, addressing2 無符號版
            SH Rd, addressing2 有符號版
            BYTE:
            B Rd, addressing1 無符號版
            SB Rd, addressing2 有符號版
            addressing1 和addressing2 的分類下面再說,現(xiàn)在理解成某種尋址方式就可以了。
            在單寄存器傳輸方面,還有以下三種變址模式,他們是:
            ◆ preindex
            這種變址方式和x86的尋址機(jī)制是很類似的,先對寄存器進(jìn)行運(yùn)算,然后尋址,但是在尋之后,基址寄存器的內(nèi)容并不發(fā)生改變,例如:
            ldr r0, [r1, #4]
            的含義就是把r1+4 這個地址處的DOWRD 加載到r0,而尋址后,r1 的內(nèi)容并不改變。
            ◆ preindex with writeback
            這種變址方式有點(diǎn)類似于++i的含義,尋址前先對基地址寄存器進(jìn)行運(yùn)算,然后尋址. 其基本的語法是在尋址符[]后面加上一個"!" 來表示.例如:
            ldr r0, [r1, #4]!
            就可以分解成:
            add r1, r1, #4
            ldr r0, [r1, #0]
            ◆ postindex
            自然這種變址方式和i++的方式就很類似了,先利用基址寄存器進(jìn)行尋址,然后對基址寄存器進(jìn)行運(yùn)算,其基本語法是把offset 部分放到[]外面,例如:
            ldr r0, [r1], #4
            就可以分解成:
            ldr r0, [r1, #0]
            add r1, r1, #4
            如果你還記得x86 的SIB 操作的話,那么你一定想ARM是否也有,答案是有也沒有。在ss上面提到的addressing1 和addressing2的區(qū)別就是比例寄存器的使用,addressing1可以使用[base, scale, 桶形移位器]來實(shí)現(xiàn)SB 的效果,或者通過[base,offset](這里的offset 可以是立即數(shù)或者寄存器)來實(shí)現(xiàn)SI 的效果,而addressing2則只能用后者了。于是每一種變址方式最多可以有3 種尋址方式,這樣一來,最多可以有9種用來尋址的指令形式。例如:
            ldr r0, [r1, r2, LSR #0x04]!
            ldr r0, [r1, -#0x04]
            ldr r0, [r1], LSR #0x04
            每樣找了一種,大概就是這個意思。到此,單寄存器傳輸就結(jié)束了,掌握這些足夠應(yīng)付差事了。下面來看看多寄存器傳輸吧。

            多寄存器傳輸
            說得很明白,意思就是通過一條指令同時(shí)把多個寄存器的內(nèi)容寫到內(nèi)存或者從內(nèi)存把數(shù)據(jù)寫到寄存器中,效率高的代價(jià)是會增加系統(tǒng)的延遲,所以armcc 提供了一個編譯器選項(xiàng)來控制寄存器的個數(shù)。指令的格式有些復(fù)雜:
            <尋址模式> Rn{!}, {r^}
            我們先來搞明白尋址模式,多寄存器傳輸模式有4 種:
            也就是說以A開頭的都是在Rn的原地開始操作,而B開頭的都是以Rn的下一個位置開始操作。如果你仍然感到困惑,我們不妨看個例子。
            所有的示例指令執(zhí)行前:
            mem32[0x1000C] = 0x04
            mem32[0x10008] = 0x03
            mem32[0x10004] = 0x02
            mem32[0x10000] = 0x01
            r0 = 0x00010010
            r1 = 0x00000000
            r3 = 0x00000000
            r4 = 0x00000000
            1) ldmia r0!, {r1-r3} 2) ldmib r0!, {r1-r3}
            執(zhí)行后: 執(zhí)行后:
            r0 = 0x0010001C r0 = 0x0010001C
            r1 = 0x01 r1 = 0x02
            r2 = 0x02 r2 = 0x03
            r3 = 0x03 r3 = 0x04
            至于DA 和DB 的模式,和IA / IB 是類似的,不多說了。
            最后要說的是,使用ldm 和stm指令對進(jìn)行寄存器組的保護(hù)是很常見和有效的功能。配對方案:
            stmia / ldmdb
            stmib / ldmda
            stmda / ldmib
            stmdb / ldmia
            繼續(xù)來看兩個例子:
            執(zhí)行前:
            r0 = 0x00001000
            r1 = 0x00000003
            r2 = 0x00000002
            r3 = 0x00000001
            執(zhí)行的指令:
            stmib r0!, {r1-r3}
            mov r1, #1 ; These regs have been modified
            mov r2, #2
            mov r3, #3
            當(dāng)前寄存器狀態(tài):
            r0 = 0x0000100C
            r1 = 0x00000001
            r2 = 0x00000002
            r3 = 0x00000003
            ldmia r0!, {r1-r3}
            最后的結(jié)果:
            r0 = 0x00001000
            r1 = 0x00000003
            r2 = 0x00000002
            r3 = 0x00000001
            另外,我們還可以利用這個指令對完成內(nèi)存塊的高效copy:
            loop
            ldmia r9!, {r0-r7}
            stmia r10!, {r0-r7}
            cmp r9, r11
            bne loop
            說到這里,讀者應(yīng)該對RISC的Load-Store體系結(jié)構(gòu)有一個大概的了解了,能夠正確配對使用指令,是很重要的。



            關(guān)鍵詞: 入門級ARM匯編指

            評論


            技術(shù)專區(qū)

            關(guān)閉