<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          ARM匯編和內(nèi)嵌匯編

          作者: 時(shí)間:2016-11-20 來(lái)源:網(wǎng)絡(luò) 收藏
          一、ldr的確是個(gè)復(fù)雜的指令,現(xiàn)總結(jié)一下:

          首先要判斷我們用的是ldr arm指令還是偽指令。 當(dāng)我們用的是arm指令時(shí),它的作用不是向寄存器里加載立即數(shù),而是將某個(gè)地址里 的內(nèi)容加載到寄存器。而偽指令ldr的作用就是向寄存器里加載立即數(shù)。
          (1) ldr偽指令
          ldr偽指令的格式是 ldr Rn, =expr
          其中,expr是要加載到Rn中的內(nèi)容,一般可以是立即數(shù)或者label。
          如果expr可以用8bit數(shù)據(jù)向右移偶數(shù)位得到,那么這條偽指令就被編譯器翻譯成mov指令。具體的移位情況可以去查閱資料。反之如果立即數(shù)很大,超過(guò)了12bit的表示范疇,那么就不能用一條mov指令了,畢竟arm指令最大只有32bit的空間可用(RISC的arm所有的指令長(zhǎng)度是一致的,效率較高,當(dāng)然我們并不關(guān)心16bit的thumb指令)。如果不能用一條32bit的指令乘下來(lái),那么就只能另辟蹊徑了,新開(kāi)一段緩沖,將立即數(shù)expr放到里面,然后將其地址(暫時(shí)標(biāo)記為addr)拿來(lái)使用:
          ldr Rn, addr
          xxx (xxx就是expr)
          xxx

          由于編譯器一般來(lái)說(shuō)新安排的存儲(chǔ)這個(gè)立即數(shù)expr的緩沖的位置是在相應(yīng)代碼的附近(這個(gè)應(yīng)該可以控制,好像是使用.ltorg偽指令)。我們從addr地址加載數(shù)據(jù)到Rn不就可以了。

          (2)ldr arm 指令
          就是將一個(gè)地址的內(nèi)容加載到寄存器。不能用mov,因?yàn)閍rm里的mov只是在寄存器之間傳輸數(shù)據(jù),不支持在寄出器和memory之間傳遞數(shù)據(jù)。因此就出現(xiàn)了ldr/str指令。如ldr Rn, addr,注意這里的addr的值也是有限制的。這個(gè)label應(yīng)該距離當(dāng)前指令的距離不超過(guò)4k。因?yàn)槲覀冎纋abel在具體使用的時(shí)候應(yīng)該是被翻譯成了相對(duì)偏移,如果這個(gè)label長(zhǎng)度不超過(guò)12bit,那么就不應(yīng)超過(guò)4k,我們可以這樣做:
          ldr pc, _start_armboot
          _start_armboot: .word arm_startboot
          這樣label _start_armboot就在指令下方,因此肯定是合法的。

          本文引用地址:http://www.ex-cimer.com/article/201611/318797.htm

          ldr r0, [r1, #4] 的含義就是把r1+4 這個(gè)地址處的DOWRD 加載到r0,而尋址后,r1 的內(nèi)容并不改變。

          ldr r0, [r1, #4]! 這種變址方式有點(diǎn)類似于++i的含義,尋址前先對(duì)基地址寄存器進(jìn)行運(yùn)算,然后尋址. 其基本的語(yǔ)法是在尋址符[]后面加上一個(gè)"!" 來(lái)表示

          二、.world

          說(shuō)說(shuō)這個(gè) .word 的作用。

          word expression 就是在當(dāng)前位置放一個(gè) word 型的值,這個(gè)值就是expression
          舉例來(lái)說(shuō),
          _rWTCON:
          .word 0x15300000

          就是在當(dāng)前地址,即 _rWTCON 處放一個(gè)值0x15300000
          不是把地址0x1530 0000 上的內(nèi)容傳遞到r1,是把地址_rWTCON上的內(nèi)容放到r1,而地址_rWTCON上的內(nèi)容是0x15300000。實(shí)際上就是把r1設(shè)置為0x15300000

          三 bic

          BIC(位清除)指令對(duì) Rn 中的值 和 Operand2 值的反碼按位進(jìn)行邏輯“與”運(yùn)算。 (注意:ARM官方網(wǎng)站有誤, 寫的是補(bǔ)碼)
          BIC 是 邏輯”與非” 指令, 實(shí)現(xiàn)的 Bit Clear的功能

          舉例:
          BIC R0, R0 , #0xF0000000
          #將 R0 高4位清零

          BIC R1, R1, #0x0F
          #將R1 低4位清0
          RSB 反向減法
          Rn, Operand2
          RSB(反向減法)指令可從 Operand2 中的值減去 Rn 中的值。
          這是很有用的,因?yàn)橛辛嗽撝噶?,Operand2 的選項(xiàng)范圍就會(huì)更大。

          例如:
          RSB r4, r4, #1280
          從1280中減去 R4

          RSB R4, R0, #0×46
          從0×46 中 減去 R0, 放入R4

          四、ADR

          ADR的定義為:小范圍的地址讀取偽指令,ADR指令將基于PC相對(duì)偏移的地址值讀取到寄存器中,在編譯源程序時(shí)ADR偽指令被編譯器 替換成一條合適的指令。通常,編譯器用一條ADD指令或SUB指令來(lái)實(shí)現(xiàn)該ADR偽指令的功能,若不能用一條指令實(shí)現(xiàn),剛產(chǎn)生錯(cuò)誤。

          在如上的定義中,有兩個(gè)關(guān)鍵信息:⑴將基于PC相對(duì)偏移的地址值讀取到寄存器中;⑵被編譯器替換成一條合適的指令。ADR指令只能將地址值讀取到寄存器中,而不能是其它的立即數(shù),并用只能用一條指令。

          如果在匯編程序中使用ADR R1,ResetHandel語(yǔ)句,其中ResetHandel是匯編程序中的一個(gè)標(biāo)簽,此條偽指令的作用是把ResetHandel標(biāo)簽所在的指令地址 讀取到寄存器R0中

          根據(jù)上面的分析,可以看到,編譯器在編譯的時(shí)候把ADR偽指令編譯成一個(gè)ADD R1,PC,Immediate指令,其中Immediate是一個(gè)立即數(shù),數(shù)值是ResetHandel語(yǔ)句和此條偽指令之間的差值,由編譯器自動(dòng)算 出。由于立即數(shù)尋址的約束,這個(gè)Immediate存在一定的約束,所以會(huì)出現(xiàn)定義中所說(shuō)的不能用一條指令實(shí)現(xiàn)。

          五、ldmia 和 stmia

          所有的示例指令執(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 是類似的,不多說(shuō)了。
          最后要說(shuō)的是,使用ldm 和stm指令對(duì)進(jìn)行寄存器組的保護(hù)是很常見(jiàn)和有效的功能。配對(duì)方案:
          stmia / ldmdb
          stmib / ldmda
          stmda / ldmib
          stmdb / ldmia
          繼續(xù)來(lái)看兩個(gè)例子:
          執(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
          另外,我們還可以利用這個(gè)指令對(duì)完成內(nèi)存塊的高效copy:
          loop
          ldmia r9!, {r0-r7}
          stmia r10!, {r0-r7}
          cmp r9, r11
          bne loop

          六、CMP

          CMP指令的格式為:
          CMP{條件} 操作數(shù)1,操作數(shù)2
          CMP指令用于把一個(gè)寄存器的內(nèi)容和另一個(gè)寄存器的內(nèi)容或立即數(shù)進(jìn)行比較,同時(shí)更新CPSR中條件標(biāo)志位的值。該指令進(jìn)行一次減法運(yùn)算,但不存儲(chǔ)結(jié)果,只 更改條件標(biāo)志位。標(biāo)志位表示的是操作數(shù)1與操作數(shù)2的關(guān)系(大、小、相等),例如,當(dāng)操作數(shù)1大于操作操作數(shù)2,則此后的有GT 后綴的指令將可以執(zhí)行。
          指令示例:
          CMP R1,R0 ;將寄存器R1的值與寄存器R0的值相減,并根據(jù)結(jié)果設(shè)置CPSR的標(biāo)志位
          CMP R1,#100 ;將寄存器R1的值與立即數(shù)100相減,并根據(jù)結(jié)果設(shè)置CPSR的標(biāo)志位

          cmp r0, #0
          beq 1f ; 如果r0==0那么向前跳轉(zhuǎn)到B處執(zhí)行
          bne 1b ; 否則向后跳轉(zhuǎn)到A處執(zhí)行1: ;
          1b,1f里的b和f表示backward和forward,1表示局部標(biāo)簽1

          TST R0, #0X8
          BNE SuspendUp ;BNE指令是“不相等(或不為0)跳轉(zhuǎn)指令”:

          LDR R1,#0x00000000

          先進(jìn)行and運(yùn)算,如果R0的第四位不為1,則結(jié)果為零,則設(shè)置zero=1(繼續(xù)下面的LDR指令);

          否則,zero=0(跳到SuspendUp處執(zhí)行)



          關(guān)鍵詞: ARM匯編內(nèi)嵌匯

          評(píng)論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();