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