/** 代碼演示 - memcpy.s **/.text.global _start.global memcpy.code 32_start:@ 將0x00008e00開始的16個字初始化成1-16mov r0, #0x00008e00mov r1, #1mov r2, #16set_loop:str r1, [r0], #4add r1, r1, #1subs r2, r2, #1bne set_loop@開始復制數據memcpy:mov r0, #0x00008e00mov r1, #0x00008f00mov r2, #16cpy_loop:ldr r3, [r0], #4str r3, [r1], #4subs r2, r2, #1bne cpy_loopmemcpy_ok:b .@在數據段分配1K的空間.data .space 1024 .end/*-----------------------代碼演示結束------------------------*/【注意】如果要仿真調試程序 1).data .space 1024 2)指定數據段的地址 arm-...-as memcpy.s -o memcpy.o arm-...-ld -T.data=0x8e00 memcpy.o -o memcpy 3)仿真調試 qemu-arm -g 1234 memcpy 另開窗口 arm-...-gdb memcpy (gdb) target remote localhostip:1234 (gdb) b 10 (gdb) c (gdb) x/16uw 0x8e00 (gdb) b 30 4)查看內存的方式 x/nfu address n,查看內存單元個數 f,format顯示內存單元的格式,x-16進制,d-10進制 u,unit單元大小,b-字節,h-半字,w-字3.2 多寄存器加載存儲指令 【加載】 'LDM{cond} <address_mode> <Rb>{!}, <Reglist>{^} !,更新地址 reglist,r0,r1,r2,r3,r4,r5(r0-r5) address_mode, ia:inc after // i增大,r0/r1/r5/r6地址分別為0x...0/4/8/C ib:inc before // i增大,r0/r1/r5/r6地址分別為0x...4/8/C/0 da:dec after // d減小,r6/r5/r1/r0地址分別為0x...0/C/8/4 db:dec before // d減小,r6/r5/r1/r0地址分別為0x...C/8/4/0 Rb,基址寄存器 ^,兩種作用,特權模式下使用用戶模式下的寄存器。 // 編號小的基地址存在低地址上。 mov r10, #0x40000000 ldmxx r10, {r0, r1, r5, r6} @// xx 為地址模式 【存儲】 'STM{cond} <address_mode> <Rb>{!}, <Reglist>{^} (同上)練習二: 使用多寄存器加載存儲指令,實現memcpy,把0x8e00開始的16個字初始化。mov r0, #0x8e00 mov r1, #0x8f00 mov r2, #4 loop: ldmia r0!, {r3, r4, r5, r6} stmia r1!, {r3, r4, r5, r6} sub r2, r2, #1 cmp r2, #0 bne loop memcpy_ok: b .3.3 棧操作指令 【加載】 'LDMxx sp!, {reglist r5-r9} 【存儲】 'STMxx sp!, {reglist r5-r9} xx,取值: FD==ia,full descend<下降> FA==ib,full ascend<上升> ED==da,empty descend EA==db,empty ascend push {fp} <==> stmfd sp!, {r11} // fp是r11的別名 pop {fp, pc} <==> ldm sp!, {fp, pc} 棧 - C語言中的作用: 1)存儲局部變量 2)緩存LR4、狀態寄存器訪問指令 'MRS(mov reg cpsr) msr r0, cpsr @//r0=cpsr 'MSR(mov cpsr reg) msr cpsr_c, r0 @//cpsr[ 7 : 0 ]=r0[ 7 : 0 ] msr cpsr_fsxc, r0 @//cpsr=r05、協處理器指令 在ARM中最多可以有16個協處理器,命名為p0 p1 p2...p15 // p15協處理器比較有名,其中也有寄存器c0 c1 c2 // p15實現大小端的設置; // DDI0500D_cortex_a53_r0p2_trm.pdf P113. 搜索big-endian [25] 'MCR(mov cooperation reg) 'MRC(mov reg cooperation)6、軟中斷指令 'SWI/SVC n(n為立即數) 該指令會導致軟中斷異常產生,該異常的產生硬件會做4件事,ARM核會切換為SVC模式。7、乘法指令 'MUL8、交換指令 'SWP
----------------------------------------------------------------------------------------------------
一、ARM指令格式【ARM采用的是32位架構】 Byte:字節,8bits HalfWord:半字,16bits Word:字,32bits // 大部分ARM core提供:ARM-32bit指令集,Thumb-16bit指令集?!続RM指令的特點】 1)沒每條指令的多功能; 2)指令都帶有條件; 3)靈活的第2操作數。【ARM指令的基本格式】 "<opcode>{<cond>} {s} <Rd> , <Rn>{, <operand2>} cond:條件碼。 如果不指定cond,則指令無條件執行。 <>:必須項。 { }:可選項。 opcode:指令助記符。 cond:執行條件。 S:是否影響CPSR狀態寄存器的值。 Rd:目標寄存器。 Rn:第1個操作數的寄存器。 // 例如: SUBNES R2, R1, #0x20 @減法運算,條件NE,結果影響CPSR operand2:第2操作數,能夠提高代碼效率。 有如下形式: #immed_8r 常數表達式(立即數) Rm 寄存器的數值 Rm,shift 寄存器移位后的數值 /* 常數表達式 - 立即數:合法性 */ 一個8位的常數通過循環右移偶數位得到,即為合法常量。 // 例如:合法常數:0xFF, 0x104, 0xFF0, 0xFF000, 0xFF000000, 0xF000000F // 例如:非法常數:0x101, 0x102, 0xFF1, 0xFF04, 0xFF003, 0xFFFFFFFF Rm:寄存器的數值 Rm,shift:寄存器移位后的值 LSL #n:邏輯左移n位 LSR #n:邏輯右移n位 ASL #n:算術左移n位 ASR #n:算術右移n位 ROR #n:循環右移n位 RRX:帶擴展的循環右移1位 // n位為2的n次方。二、ARM數據操作指令【數據處理指令】 1)數據傳送指令 2)算術運算指令 3)邏輯運算指令 4)比較指令 5)測試指令 6)乘法指令《opcode操作碼功能表》AND/EOR/SUB/RSB/ADD/ADC/SBC/RSC/TST/TEQ/CMP/CMN/ORR/MOV/BIC/MVN【數據傳送指令】 mov/mvn ' mov{cond}{s} Rd, operand2 將8位立即數或寄存器傳送到目標寄存器Rd中。 // 用于移位運算等操作。 ' mvn{cond}{s} Rd, operand2 將8位立即數或寄存器按位取反后傳送到目標寄存器Rd中。 // 取反功能,可使寄存器裝載范圍更廣的立即數?!舅阈g運算指令】add/sub/rsb/adc/sbc/rsc add:加法 sub:減法 rsb:逆向減法 adc:帶進位加法 sbc:帶進位減法 rsc:帶進位逆向減法 ' add{cond}{s} Rd, Rn, operand2 將operand2的值與Rn的值相加,結果保存到Rd寄存器。 // 其他算術運算指令等同于add。【邏輯運算指令】and/orr/eor/bic and:邏輯與 orr:邏輯或 eor:邏輯異或 bic:位清除(按位清0,其他位不變) ' and{cond}{s} Rd, Rn, operand2 將operand2的值與寄存器Rn的值按位作邏輯"與&"操作,結果保存到Rd中。 // 其他邏輯運算指令等同于and。---> 嵌入式控制寄存器的移位操作常用?!颈容^指令】cmp/cmn/tst/teq - 用的比較多! cmp:比較(本質:相減,影響cpsr標志位) cmn:負數比較(本質:相加,影響cpsr標志位) tst:位測試(本質:邏輯與,影響cpsr標志位) teq:相等測試(本質:邏輯異或,影響cpsr標志位) ' cmp{cond} Rn, operand2 將寄存器Rn的值減去operand2的值,根據操作結果更新CPSR中的響應條件標志位,以便后面的指令根據相應的條件標志來判斷是否執行。 // 【注意】比較指令的本質是做算術運算,但唯一區別是并不保存運算結果。 // 【錯例】cmp r2, r15, asr r0 @r15不允許與被控制移位的寄存器一起出現,在有移位操作的情況下,不能將r15用于任何操作數?!境朔ㄖ噶睢縨ul/mla/umull/umlal/smull/smlal mul:32bit乘法 mla:32bit乘加 ' mul{cond}{s} Rd, Rm, Rs 將Rm和Rs中的值相乘,結果的低32位保存到Rd中。 ' mla{cond}{s} Rd, Rm, Rs, Rn 將Rm和Rs中的值相乘,再將結果加上第3個操作數Rn,結果的低32位保存到Rd中。 // 【注意】r15不能用作rd, rm, rs, rn,且rd不能與rm相同。 umull/umlal/smull/smlal 均為64位指令。 umull:64bit無符號乘法 umlal:64bit無符號乘加 smull:64bit有符號乘法 smlal:64bit有符號乘加【分支指令】b/bl/bx b:分支指令branch bl:帶鏈接的分支指令branch with link bx:帶狀態切換的分支指令branch and exchange(bx{cond} Rm) ' b{cond} label 跳轉范圍限制±32M字節地址內(ARM為字對齊,最低2位地址固定為0) // 【注意】bl指令需要與 mov pc, lr 一起使用,實現返回指定地址。【軟中斷指令】swi swi:軟中斷 ' swi{cond} immed_24 實現從用戶模式變換到管理模式。三、ARM指令的尋址方式 ARM處理器具有 7 種基本的尋址方式: 1)立即尋址; // 立即尋址就是立即數尋址,操作數直接通過指令給出。 2)寄存器尋址; // 指令中的地址碼是寄存器編號,執行時直接取寄存器的值來操作。 3)寄存器間接尋址; // 通過load/store完成對數據的傳送操作。利用一個寄存器的值作為存儲器地址,在指定的寄存器中存放有效地址,而操作數則放在存儲單元中。 4)基址尋址; // 將基址寄存器的內容與指令中給出的偏移量相加,形成操作數的有效地址。 5)相對尋址; // 由程序計數器PC提供基準地址,指令中的地址碼字段作為偏移量,兩者相加后得到的地址為操作數的有效地址。 6)堆棧尋址; // 后進先出。使用一個專門的寄存器(堆棧指針)指向一塊存儲區域(堆棧),指針所指向的存儲單元即是堆棧的棧頂。向上-遞增堆棧,向下-遞減堆棧。 7)塊拷貝尋址; // 將寄存器內容復制到寄存器的地址所指示的存儲器中,需要注意的是在存儲第一個值之后存儲器地址是增加還是減少。 ia - 傳送后,地址+4 ib - 傳送錢,地址=4 da - 傳送后,地址-4 db - 傳送后,地址-4四、存儲器訪問指令 ARM處理器是load/store型的,即它對數據的操作是通過將數據從存儲器加載到片內寄存器中進行處理,處理完成后的結果經過寄存器存回到存儲器中,以加快對片外存儲器進行數據處理的執行速度?!締渭拇嫫骷虞d】ldr ldr:加載字數據 ldrb:加載無符號字節數據 ldrt:以用戶模式加載字數據 ldrbt:以用戶模式加載無符號字節數據 ldrh:加載無符號半字數據 ldrsb:加載有符號字節數據 ldrsh:加載有符號半字數據【單寄存器存儲】str str:存儲字數據 strb:存儲字節數據 strt:以用戶模式存儲字數據 strbt:以用戶模式存儲字節數據 strh:存儲半字數據【字和無符號字節的加載/存儲指令】 ' ldr{cond}{t} Rd, <地址> 將制定地址上的字數據讀入Rd。 ' str{cond}{t} Rd, <地址> 將Rd中的字數據存入制定地址。 ' ldr{cond}b{t} Rd, <地址> 將制定地址上的字節數據讀入Rd。 ' str{cond}b{t} Rd, <地址> 將Rd中的字節數據存入制定地址。 // t 代表處理器是在特權模式下,存儲系統也將訪問看成是在用戶模式下進行的。
新聞熱點
疑難解答
圖片精選