/** 代碼演示 - 最簡單的匯編程序 **/.text @代表接下來的內(nèi)容放入代碼段.code 32 @代表接下來的內(nèi)容翻譯成ARM指令集.global start @聲明全局start標(biāo)號(hào)start:mov r0, #10 @ r0=10b . @ goto 當(dāng)前位置執(zhí)行,構(gòu)成執(zhí)行死循環(huán).end @ 代表整個(gè)匯編文件的結(jié)束$:arm-cortex_a9-linux-gnueabi-as test.s -o test.o // 編譯匯編代碼$:arm-cortex_a9-linux-gnueabi-objdump -S test.o > 1.asm// 反匯編4、 ARM匯編的特點(diǎn) 匯編語言,又叫助記符語言。 1)大多數(shù)指令都是單周期指令 2)大多數(shù)指令都是可以條件執(zhí)行的。--------------------【條件碼】--------------------CMP: 比較EQ: 相等NE: 不等ADD: 加法CS: 無符號(hào)數(shù)大于或等于CC: 無符號(hào)數(shù)小于 5、ARM匯編指令 5.1 分支跳轉(zhuǎn)指令 'B{cond} <target_address> '分支指令 - 類似于goto {} 代表可由可無,<>代表缺少就報(bào)錯(cuò),cond為指令執(zhí)行的條件碼,target_address為指令跳轉(zhuǎn)的目標(biāo)地址。 'BL{cond} <target_address> '相對(duì)跳轉(zhuǎn)指令 - 類似于函數(shù)調(diào)用 跳轉(zhuǎn)范圍限制±32M,PC=PC±32M 【L】決定由硬件自動(dòng)保存下調(diào)指令的返回地址到lr,用于函數(shù)調(diào)用 // B和BL指令均可跳轉(zhuǎn)到指令中的目標(biāo)地址。-地址相關(guān)碼/地址無關(guān)碼 'BX{cond} <Rm>' 絕對(duì)跳轉(zhuǎn),4G范圍 BLX 【X】帶狀態(tài)切換的分支跳轉(zhuǎn)5.2 數(shù)據(jù)處理指令 0)移位操作 lsl:邏輯左移 logical shift left,最低位補(bǔ)0 lsr:邏輯右移 logical shift right,最高位補(bǔ)0 asr:算術(shù)右移 arithmetic shift right,最高位補(bǔ)符號(hào)位,最低位舍棄 ror:循環(huán)右移 ,最低位變成新的最高位 rrx:帶擴(kuò)展位的循環(huán)右移,最高位擴(kuò)展cpsr的C位 1)數(shù)據(jù)傳輸指令 'MOV{cond} {s} <Rd>, <Operand> cond:可以條件執(zhí)行 s:操作結(jié)果影響cpsr N/Z/C位 Rd:目標(biāo)寄存器 operand:目標(biāo)操作數(shù) 立即數(shù):mov r0, #1 /* 注意立即數(shù)的合法性問題,該立即數(shù)可以通過1個(gè)8bit位數(shù)循環(huán)右移得到*/ 寄存器:mov r0, r1 @ r0=r1 寄存器移位之后的值: mov r0, r1, LSL #2 @ r0=r1*4 mov r0, #0 @ 把數(shù)字0放到r0寄存器 movs r0, #0 @ r0=0 N=0 Z=1 C=0 movCSS r0, r2 'MVN r0, #1 @ r0= ~(1) 2)算術(shù)運(yùn)算指令 'ADD{cond} {s} <Rd>, <Rm> <shifter_operand> 加法 cond:條件碼 s:操作結(jié)果影響cpsr N/Z/C/V位 Rd:目標(biāo)寄存器,r0~r15其中任意一個(gè) Rm:第一個(gè)操作數(shù),r0~r15其中任意一個(gè) operand:第二個(gè)操作數(shù) 立即數(shù):add r0, r1, #8 @ r0=r1+8 // 錯(cuò)誤示范:add r0, #8, r1 寄存器:add r0, r1, r2 @ r0=r1+r2 寄存器移位之后的值: add r0, r1, r2, lsl #2 @ r0=r1+r2*4 add r0, r1, r2 @ r0=r1+r2 adds r0, r1, r2 @ r0=r1+r2 操作結(jié)果r0影響N/Z/C/V位 'ADC r0, r1, r2 @ r0=r1+r2+C 帶進(jìn)位的加法指令 64位加法運(yùn)算: 高 低 加數(shù) r0 r1 被加數(shù) r2 r3 和 r0 r1 adds r1, r1, r3 @ 改變C adc r0, r0, r2 @r0=r0+r2+C 'SUB/SBC/RSB{cond} {s} <Rd>, <Rm> <shifter_operand> 減法 cond:條件執(zhí)行 s:操作結(jié)果影響cpsr N/Z/C/V // 注意對(duì)C位的影響: // 如果最高位沒有借位 - C=1 - 如 100-20 // 如果最高位有借位 - C=0 - 如 20-100 Rd:目標(biāo)寄存器,r0~r15其中任意一個(gè) Rm:第一個(gè)操作數(shù),r0~r15其中任意一個(gè) operand:第二個(gè)操作數(shù)(同ADD) 立即數(shù) 寄存器 寄存器移位后的值 sub r0, r1, r2 @ r0=r1-r2 sub r0, r1, #8 @ r0=r1-8 sub r0, r1, r2, lsl #1 @r0=r1-r2*2 'SBC r0, r1, r2 @ r0=r1-r2-NOT(C) rsb r0, r1, r2 @r0=r2-r1 rsb r0, r0, #0 @r0=0-r0 64bit減法運(yùn)算: 高 低 被減數(shù) r0 r1 減數(shù) r2 r3 差 r0 r1 subs r1, r1, r3 @ r1=r1-r3 if (r1>r3) {C=1} if (r1<r3) {C=0} sbc r0, r0, r2 @ r0=r0-r2-NOT(C)練習(xí)一:使用匯編語言求1-10的累加和,結(jié)果保存到r0中。
/** 代碼演示 - **/.text.code 32.global _start_start: mov r0, #0 @// 將0放入r0 mov r1, #10 @// 將10放入r1sub_loop: add r0, r0, r1 @// r0=r0+r1; sub r1, r1, #1 @// r1=r1-1; cmp r1, #0 @// 判斷:r1 ?= 0 bne sub_loop @// ne不相等 b跳轉(zhuǎn)到 b . .end/** ------------------------------------------------------- **/ $:arm-cortex_a9-linux-gnueabi-as sum.s -o sum.o $:arm-cortex_a9-linux-gnueabi-ld sum.o -o sum // 可以通過仿真軟件qemu,在PC機(jī)上模擬arm core的執(zhí)行過程 安裝qemu: 聯(lián)網(wǎng)安裝:$:sudo apt-get install qemu... 非聯(lián)網(wǎng)安裝:$: cd ~/Downloads/qemu $: sudo dpkg -i *.deb 重新編譯sum程序: $: cd - $:arm-cortex_a9-linux-gnueabi-as sum.s -o sum.o -g $:arm-cortex_a9-linux-gnueabi-ld sum.o -o sum 調(diào)試運(yùn)行程序: $:qemu-arm -g 1234 sum // 1234為端口 另開一個(gè)shell窗口,cd進(jìn)到程序文件目錄 $:arm-cortex_a9-linux-gnueabi-gdb sum (gdb)target remote 192.168.1.8:1234 // localhost(ip) (gdb)b 8 (gdb)c (gdb) info reg r1 // 查看r1寄存器里面的值,r1 = 10 (gdb)n (gdb)info reg r1 // r1 = 9 (gdb)b 16 (gdb)c (gdb)info reg r0 // r0 = 19 注意: $: arm-cortex_a9-linux-gnueabi-gdb sum arm-cortex_a9-linux-gnueabi-gdb: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.16` not found (required by arm-cortex_a9-linux-gnueabi-gdb) 此時(shí)需要做的是安裝libc6的庫: $: cd ~/Downloads/ $: sudo dpkg -i *.deb 3)邏輯運(yùn)算指令 'AND/ORR/EOR{cond} {s} <Rd>, <Rm>, <operand>' and r0, r1, #0x80 @ r0=r1&0x80 orr r5, r8, r7 @ r5=r8|r7 eor r5, r6, r7, lsl #2 @ r5=r6^(r7*4) 將r0中的bit15位取反? mov r1, #1 eor r0, r0, r1, lsl #15 'BIC{cond} {s} <Rd>, <Rm>, <operand>' bic r0, r0, #0x08 @ 將r0的bit3位清0,其他bit位保持不變 bic r0, r0, #0xff @ 將r0的低8位全部清0 將r0的bit7位清0,其他位保持不變? move r1, #1 bic r0, r0, r1 lsl #7 4)比較測(cè)試指令 該類指令不用加s,默認(rèn)就能影響cpsr的N/Z/C/V位 運(yùn)算結(jié)果不保存。 'CMP/CMN{cond} <Rm>, <operand> ' cmp r0, #0x08 @alu_out=r0-0x08 // alu_out算邏單元 @ if (r0<0x08) N=1 反之N=0 @ if (r0==0x08) Z=1 反之Z=0 @ if (r0>0x08) C=0 反之C=1 cmp r1, r2 cmp r1, r2, lsl #1 'TST{cond} <Rn>, <operand> tst r1, #0x08 @ alu_out=r1&0x08 @ 根據(jù)alu_out取值去影響cpsr N/Z/C/V @ 測(cè)試r1 bit3是否為0 如果r1 bit3為0,Z=1 'TEQ{cond} <Rn>, <operand> teq r1, r2 @ alu_out=r1^r2 如果兩個(gè)數(shù)據(jù)相等alu_out=0,Z=1練習(xí)二: 求兩個(gè)數(shù)據(jù)的最大公約數(shù)。 r0 r1 eg: 120 48 // 每次相減,把結(jié)果與運(yùn)算的數(shù)對(duì)比,取小的放有側(cè) 72 48 24 24 // r0,r1兩個(gè)寄存器的數(shù)相等的時(shí)候,即得結(jié)果 r0 r1/** 代碼演示 - gcd.s **/.text.global _start.global gcd.code 32_start: mov r0, #20 @存放參數(shù)1 mov r1, #12 @存放參數(shù)2gcd: cmp r0, r1 beq gcd_ok subcs r0, r0, r1 subcc r1, r1, r0 b gcdgcd_ok: @ R0,R1相等為最大公約數(shù)。 b ..end
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注