首页 > 编程 > ASM > 正文

ARM:ARM汇编语言与基础汇编指令

2019-11-08 02:13:09
字体:
来源:转载
供稿:网友
1、为什么要学习汇编语言?    1)嵌入式硬件上电的初始化代码是用汇编代码编写;    2)调试代码时,问题的解决有可能看汇编代码;    3)系统调优(提高产品整体运行效率);        memcpy:C语言函数原型                     :汇编代码 - 效率更高    4)有些逻辑,拿C语言无法实现         例如,用c访问r5寄存器         register int a;2、学习目标    1)使用汇编控制LED灯;    2)可以阅读汇编代码。3、学ARM汇编要学的内容    汇编指令    伪指令    伪操作
/** 代码演示 - 最简单的汇编程序 **/.text  @代表接下来的内容放入代码段.code 32  @代表接下来的内容翻译成ARM指令集.global start  @声明全局start标号start:mov r0, #10  @ r0=10b .  @ goto 当前位置执行,构成执行死循环.end  @ 代表整个汇编文件的结束$:arm-cortex_a9-linux-gnueabi-as test.s -o test.o // 编译汇编代码$:arm-cortex_a9-linux-gnueabi-objdump -S test.o > 1.asm// 反汇编4、 ARM汇编的特点    汇编语言,又叫助记符语言。    1)大多数指令都是单周期指令    2)大多数指令都是可以条件执行的。--------------------【条件码】--------------------CMP:    比较EQ:       相等NE:       不等ADD:     加法CS:        无符号数大于或等于CC:        无符号数小于  5、ARM汇编指令  5.1 分支跳转指令    'B{cond}  <target_address> '分支指令 - 类似于goto        {} 代表可由可无,<>代表缺少就报错,cond为指令执行的条件码,target_address为指令跳转的目标地址。    'BL{cond} <target_address> '相对跳转指令 - 类似于函数调用        跳转范围限制±32M,PC=PC±32M    【L】决定由硬件自动保存下调指令的返回地址到lr,用于函数调用    // B和BL指令均可跳转到指令中的目标地址。-地址相关码/地址无关码    'BX{cond} <Rm>' 绝对跳转,4G范围    BLX    【X】带状态切换的分支跳转5.2 数据处理指令    0)移位操作        lsl:逻辑左移 logical shift left,最低位补0        lsr:逻辑右移 logical shift right,最高位补0        asr:算术右移 arithmetic shift right,最高位补符号位,最低位舍弃        ror:循环右移 ,最低位变成新的最高位        rrx:带扩展位的循环右移,最高位扩展cpsr的C位    1)数据传输指令        'MOV{cond} {s} <Rd>, <Operand>            cond:可以条件执行            s:操作结果影响cpsr N/Z/C位            Rd:目标寄存器            operand:目标操作数                            立即数:mov r0, #1  /* 注意立即数的合法性问题,该立即数可以通过1个8bit位数循环右移得到*/                            寄存器:mov r0, r1  @ r0=r1                            寄存器移位之后的值:                                        mov r0, r1, LSL #2  @ r0=r1*4            mov r0, #0  @ 把数字0放到r0寄存器            movs r0, #0  @ r0=0 N=0 Z=1 C=0            movCSS r0, r2        'MVN r0, #1   @ r0= ~(1)    2)算术运算指令        'ADD{cond} {s} <Rd>, <Rm> <shifter_operand>  加法            cond:条件码            s:操作结果影响cpsr N/Z/C/V位            Rd:目标寄存器,r0~r15其中任意一个            Rm:第一个操作数,r0~r15其中任意一个            operand:第二个操作数                            立即数:add r0, r1, #8  @ r0=r1+8                                        // 错误示范: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  操作结果r0影响N/Z/C/V位        'ADC r0, r1, r2  @ r0=r1+r2+C  带进位的加法指令        64位加法运算:                        高     低             加数     r0     r1             被加数  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:条件执行            s:操作结果影响cpsr N/Z/C/V            // 注意对C位的影响:            // 如果最高位没有借位 - C=1 - 如 100-20            // 如果最高位有借位 - C=0 - 如 20-100            Rd:目标寄存器,r0~r15其中任意一个            Rm:第一个操作数,r0~r15其中任意一个            operand:第二个操作数(同ADD)                            立即数                            寄存器                            寄存器移位后的值            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减法运算:                            高        低            被减数       r0        r1            减数          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)练习一:

    使用汇编语言求1-10的累加和,结果保存到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跳转到    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机上模拟arm core的执行过程    安装qemu:        联网安装:$:sudo apt-get install qemu...        非联网安装:$: 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    调试运行程序:        $:qemu-arm -g 1234 sum   // 1234为端口        另开一个shell窗口,cd进到程序文件目录        $: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)    此时需要做的是安装libc6的库:    $: cd ~/Downloads/    $: sudo dpkg -i *.deb    3)逻辑运算指令        '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)比较测试指令        该类指令不用加s,默认就能影响cpsr的N/Z/C/V位        运算结果不保存。        '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                                      @ 根据alu_out取值去影响cpsr N/Z/C/V                                      @ 测试r1 bit3是否为0                                          如果r1 bit3为0,Z=1        'TEQ{cond} <Rn>, <operand>            teq r1, r2    @ alu_out=r1^r2                                  如果两个数据相等alu_out=0,Z=1练习二:    求两个数据的最大公约数。               r0  r1    eg: 120  48  // 每次相减,把结果与运算的数对比,取小的放有侧                 72    48                      24    24  // r0,r1两个寄存器的数相等的时候,即得结果                        r0    r1
/** 代码演示 - gcd.s **/.text.global _start.global gcd.code 32_start:    mov  r0, #20          @存放参数1    mov  r1, #12          @存放参数2gcd:    cmp r0, r1    beq gcd_ok    subcs r0, r0, r1    subcc r1, r1, r0    b   gcdgcd_ok:    @ R0,R1相等为最大公约数。    b    ..end
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选