物聯網之ARM體系結構及接口技術二(ARM指令)

ARM指令

搬移指令

mov   r13,#3

mov   r0,r1

mov   r0,r1,LSL#2                      @LSL#2表示邏輯左移兩位,將r1左移兩位之後的數值賦給寄存器r0    

mov   r0,r1,LSR#2                      @LSR#2表示邏輯右移兩位,將r1右移兩位之後的數值賦給寄存器r0

mrs   r0,cpsr                               @讀取cpsr寄存器的值,賦給r0。注意特殊寄存器的讀取使用mrs指令

msr   cpsr,r0                               @將r0的值賦給cpsr。注意特殊寄存器的寫入使用msr指令

條件執行

if (a==0)   x=0;
if (a>0)     x=x+3;

cmp       r0,#0                    @比較r0與0是否相等
moveq   r1,#0                    @mov是上面講過的搬移指令,eq判斷上一條指令執行的結果是否相等,如果相等,則將0賦值給r1
addgt     r1,r1,#3                @add是加法運算,gt判斷cmp指令r0是否大於0,如果大於零,則將r1+3的值賦給r1

指令是如何存儲的,如何被解析的?

          寫c代碼--------------------------------->生成彙編代碼------------------------->FLASH中最終存儲機器指令(二進制)

指令機器碼(FLASH中最終存儲機器指令(二進制)進行解析

當賦給寄存器的值過大時(一般大於255),就要使用僞指令對其賦值:ldr r0,=0x123456

邏輯指令

and r0,r1,#0xFF   // r0 = r1&0xFF(與運算)

 orr r3,r0,#0x0F   // r3 = r0|0x0F (或運算)     

 bic r0,r0,#0x03   // 清除r0中的0號位和1號位 

 tst r0,#0x20      //測試第6位是否爲0 ,爲0則Z標誌置1 

 cmp r1,r0         //將R1與R0相減做比較,並根據結果設置CPSR的標誌位

• 使能中斷和快速中斷?

        mrs   r0,cpsr

        bic   r0,r0,#0xc0  (清零F位和I位)

        msr   cpsr,r0

• 判斷當前工作狀態是否是ARM狀態,是則切換到user 工作模式?

        mrs   r0,cpsr

        tst   r0,#0x20

        andeq   r0,r0,#0xFFFFFFE0 (低5位清零)

        orreq   r0,r0,#0x10

        msreq   cpsr,r0

算術指令

add r0,r1,r2    //r0=r1+r2

sub  r0,r1,#3   //r0= r1 - 3

sub  r0,r1,r2,LSL#1    //r0=r1-(r2<<1)

mul  r1,r2,r3   //r1=r2*r3

跳轉指令

 b     main      //跳轉到標號爲main地代碼處 

 bl     func     //保存下一條要執行的指令的位置到 LR寄存器,跳轉函數func

                 //當跳轉代碼結束後,用MOV PC,LR指令跳回來

 beq    addr     //當CPSR寄存器中的Z條件碼置位時,跳轉到該地址處

 bne  addr       //當不等時,跳轉到地址addr

用匯編實現下面功能:

void main(void)
{
    int ret=0;
    func1(2);
    while(1) {};   	
}
	
func1(int a)
{
    if(a==2)
       return func2(a);
    else
       return func3(a);  
}

func2(int a) 
{    
    return a+3;
} 

func3(int a)
{    
    return a-1;
} 

實現 延時1秒函數:

@delay fos 1 second
delay1s:    
    ldr    r4,=0x3FFFF
loop_delay1s:
    sub    r4,r4,#1
     cmp    r4,#0         
     bne    loop_delay1s
delay1s_end:
    mov    pc,lr

測驗:

用匯編實現求最大公約數?(如9 15 值是3) 

int GCD(int a,int b)
{	 	  
 	 while(1)
 	 {
       if(a==b)
         break; 	
       if(a>b){
	       a=a-b;
       }else{
          b=b-a;  	
       }	
    } 		
    return a;	 	   
} 	

Load/Store 指令

注:load/store架構規定,存儲器之間不能直接拷貝,需通過寄存器做中轉 (比如講FLASH中的指令傳入到內存中就必須使用CPU寄存器做中轉)

 ldr r0,[r1]  (load)   //r0=*r1    r1裏存放的是地址,把該地址裏存放的內容讀入到r0中   

                       //LDRB(byte)  LDRH(half word)    

 ldr r0,[r1,#8]      //r0=*(r1+8)  存儲器地址爲r1+8的字數據讀入寄存器0。

 ldr pc,_irq           // pc = *(_irq)  將標號中的內容放入pc中

 str r0,[r1] (store)   // *r1 = r0   將寄存器r0中值寫入到存儲器地址爲r1的空間中 

 str r0,[r1],#4        // r0=*r1, r1=r1+4  將r0 中的字數據寫入以r1爲地址的內存中,並將新地址r1+4 寫入r1

 str r0,[r1,#4]        //*(r1+4)=r0  將r0 中的字數據寫入以r1+4 爲地址的內存中   

Pre or Post Indexed 尋址

Pre-indexed: STR r0,[r1,#12]

拷貝srcBuf裏內容 到destBuf中:

  .text

     ldr  r0,=srcBuf

     ldrb  r1,[r0]

     ldr  r0,=destBuf

     strb  r1,[r0]

  srcBuf:  

     .byte  0x01,02,0x03,0x04

 .data

destBuf:

      .space 8

 .end

測驗

用匯編實現下面功能

main()
{
   int i=0;
   const  char buf[]={1,2,3};
   char destBuf[8];
   for(i=0,i<3,i++)
   {
	  destBuf[i] = buf[i];
   }
}

GNU 彙編僞指令

   .text                     將定義符開始的代碼編譯到代碼段

  .data                     將定義符開始的代碼編譯到數據

  .end                      文件結束

  .equ  GPG3CON, 0XE03001C0 定義宏(即用GPG3CON代替 0XE03001C0)

  .byte                  定義變量 1字節                   

                            .byte   0x11,'a',0 定義字節數組 

  .word                  定義word變量 (4字節   32位機)  

                            .word 0x12344578,0x33445566

  .string                   定義字符串         .string  "abcd\0"

   ldr r0,=0xE0028008      載入大常數0xE0028008 到r0中

           .global  _start           聲明_start 爲全局符號

例  拷貝ROM中字符串到RAM中

   .text

start:

    ldr  r5,=srcBuf

    ldr  r6,=destBuf

loop:

    ldrb r4,[r5]

    cmp  r4,#0

    beq  main_end

    ldrb  r0,[r5],#1

    strb  r0,[r6],#1

    b   loop

main_end:

    b    main_end

srcBuf:

    .string  "abcdefg\0"

    .data

destBuf:

    .space  8

.end

批量操作指令

• 批量操作指令     (ia-Increment After  ib-Increment Before  da-Dec After db-Dec Before)

   ldmia  r0!, {r3 - r10}   //r0裏地址指向的內容批量,load 到r3~r10寄存器中, r0裏地址會自動加4

   stmia  r0!, {r3 - r10}   //把r3~r10寄存器中內容,store 到r0裏地址執行空間中,r0裏地址會自動加4

• 例:實現塊數據批量拷貝

   r12指向源數據起始地址   

   r14指向源數據尾地址

   r13指向目的數據起始地址

例  批量拷貝數據

  .text

   ldr r12,=srcBuf

   ldr r13,=dstBuf

   ldmia  r12!,{r0 - r11}

   stmia  r13!,{r0 - r11}

  .data

srcBuf:

  .string "abdfasdf13535dfksjdlfkjlksldkjflkl\0"

srcBuf_end:  

dstBuf:

  .space  12*4

  .end

堆棧操作指令

stmfd sp!,{r0-r12,lr}   將寄存器r0~r12 lr中的值存入棧中   

                                 常用於中斷保護現場,! 表示會自動偏移                                       

 ldmfd sp!,{r0-r12,pc}^  將棧中值逐個彈出到寄存器r0~r12 pc中 

                                 常用於中恢復斷現場,^表示會恢復spsr到cpsr

ARM 指令 高級

• 軟中斷指令

   swi 0x02  產生軟中斷, 軟中斷號爲2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章