• 国庆假期作业6


    一、ARM的工作模式

    1、非特权模式

            user模式:非特权模式,大部分任务执行在这种模式

    2、特权模式

            异常模式:

            FIQ : 当一个快速(fast) 中断产生时将会进入这种模式

            IRQ : 当一个通用(normal) 中断产生时将会进入这种模式

            Supervisor(svc) :当复位或软中断指令执行时将会进入这种模式

            Abort : 当存取异常时将会进入这种模式

            Undef : 当执行未定义指令时会进入这种模式        

            非异常模式:

            System : 使用和User模式相同寄存器集的特权模式

    二、汇编语言的相关语法

    1、汇编语言的组成部分

    1. 1.伪操作:不参与程序的执行,但是用于告诉编译器程序该怎么编译
    2. .text
    3. .global .end .if .else .endif .data
    4. 2.汇编指令
    5. 编译器将一条汇编指令编译成一条机器码,在内存里一条指令占4字节内存,一条指令可以实现一个特定的功能
    6. 3.伪指令
    7. 不是指令,看起来像是一条指令,可以实现和指令类似的功能。一条伪指令实际上可能是由多条指令共同实现
    8. 4.注释
    9. 单行注释: @
    10. 多行注释 /* */
    11. 条件编译
    12. .if 0
    13. 指令段
    14. .else
    15. 指令段
    16. .endif

    2.汇编指令的介绍

    1. 1.基本数据操作指令
    2. 数据搬移指令 =
    3. 数据移位指令 << >>
    4. 数据算数运算指令 + - * /
    5. 位运算指令 & | ~ ^
    6. 数据比较指令
    7. 2.跳转指令
    8. 3.内存读写指令
    9. 4.状态寄存器读写指令
    10. 5.软中断指令

    3.汇编指令的基本语法格式

    1. 指令的基本格式:
    2. <opcode>{<cond>}{s} <Rd>, <Rn>, <shifter_operand>
    3. 解释:
    4. <opcode>:指令码
    5. {<cond>}:条件码
    6. {s}:状态位,如果在指令后面加上s,则运算的结果会影响CPSR的条件位
    7. <Rd>:目标寄存器
    8. <Rn>:第一操作寄存器 只能是寄存器
    9. <shifter_operand>:第二操作数,可以是寄存器,也可以是立即数
    10. 按照指令码将第一操作寄存器和第二操作数进行运算,将运算后的结果保存在目标寄存器
    11. 注意:
    12. 1.一条汇编指令一般占一行
    13. 2.汇编不区分大写小写

    三、汇编指令

    1.数据搬移指令

    1. <opcode>{<cond>}{s} <Rd>, <shifter_operand>
    2. 解释:
    3. <opcode>:指令码
    4. {<cond>}:条件码
    5. {s}:状态位,如果在指令后面加上s,则运算的结果会影响CPSR的条件位
    6. <Rd>:目标寄存器
    7. <shifter_operand>:第一操作数,可以是寄存器,也可以是立即数
    8. 按照指令码将第一操作数运算后的结果保存在目标寄存器
    9. 指令码功能:
    10. mov:将第一操作数的值保存在目标寄存器
    11. mvn:将第一操作数的值按位取反,将结果保存在目标寄存器

    2、移位指令

    2.1 格式以及指令码

    1. 格式:<opcode>{<cond>}{s} <Rd>, <Rn>, <shifter_operand>
    2. 解释:将第一操作寄存器的数值移位第二操作数指定的位数,将结果保存在目标寄存器中
    3. 指令码:
    4. LSL:左移运算 低位补0
    5. LSR:右移运算 高位补0
    6. ROR:循环右移:低位移出的值补到高位

    2.2 示例

    1. 1.左移
    2. mov r0,#0XFF
    3. lsl r1,r0,#0X4 @将R0的值左移4位保存在r1寄存器 R1结果:0XFF0
    4. 2.右移
    5. mov r0,#0XFF
    6. lsr r1,r0,#0X4 @将R0的值右移4位保存在r1寄存器 R1结果:0XF
    7. 3.循环右移
    8. mov r0,#0XFF
    9. ror r1,r0,#0X4 @将R0的值循环右移4位保存在r1寄存器 R1结果:0XF000000F
    10. 4.c风格写法
    11. mov r0,#0XFF
    12. ror r1,r0,#(0X1<<2) @将R0的值循环右移4位保存在r1寄存器 R1结果:0XF000000F

    3.位运算指令

    3.1 格式以及功能码

    1. 格式:<opcode>{<cond>}{s} <Rd>, <Rn>, <shifter_operand>
    2. 解释:将第一操作寄存器和第二操作数进行位运算,将结果保存在目标寄存器中
    3. 指令码:
    4. and:与 与001不变
    5. orr:或 或110不变
    6. eor:异或 相同为0 不同为1
    7. bic:按位清零指令,想将哪一位设置为0,只需要用bic指令给这一位运算一个1即可

    3.2 示例

    1. 1.and:
    2. mov r0,#0XFF
    3. and r1,r0,#0XF0 @R1结果为0XF0
    4. 2.ORR:
    5. mov r0,#0XFF
    6. orr r1,r0,#0XF000 @R1结果为0XF0FF
    7. 3.EOR:
    8. ldr r0,=0xf0f0
    9. EOr r1,r0,#0XFF @R1结果为0XF00F
    10. 0000 0000 0000 0000 0000 0000 1111 1111
    11. 0000 0000 0000 0000 1111 0000 1111 0000
    12. 结果:0000 0000 0000 0000 1111 0000 0000 1111 -》0XF00F
    13. 4.BIC
    14. ldr r0,=0xFF
    15. BIC r0,r0,#(0x1<<5) @将R0的值第5位清0 @R0结果为0XDF

    3.3 练习

    1. LDR r1,=0X12345678 @将0X12345678存放在r1寄存器
    2. 0001 0010 0011 0100 0101 0110 0111 1000
    3. 1.将R1寄存器的第4位清0,其他位不变
    4. and r1,r1,#(~(0X1<<4))
    5. 或者BIC R1,R1,#(0x1<<4)
    6. 2.将r1寄存器第7位置1,其他位不变
    7. orr r1,r1,#(0X1<<7)
    8. 3.将r1寄存器[3128]清0,其他位不变
    9. and r1,r1,#(~(0Xf<<28))
    10. 或者BIC R1,R1,#(0xF<<28)
    11. 4.将r1寄存器[7:4]置1,其他位不变
    12. orr r1,r1,#(0XF<<4)
    13. 5.将r1寄存器[15:11]设置为10101,其他位不变
    14. @先清0
    15. BIC R1,R1,#(0X1F<<11)
    16. @再置位
    17. orr r1,r1,#(0X15<<11)

    4.算数运算指令

    4.1 格式以及指令码

    1. 格式:<opcode>{<cond>}{s} <Rd>, <Rn>, <shifter_operand>
    2. 解释:将第一操作寄存器的值和第二操作数进行算数运算,结果保存在目标寄存器中
    3. add:加法运算
    4. adc:进行加法运算时需要考虑CPSR的条件位
    5. sub:减法运算
    6. sbc:进行减法运算时需要考虑CPSR的条件位
    7. mul:乘法运算

    4.2 示例

    1. 1.ADD:加法
    2. ex1: mov r1,#1
    3. mov r2,#2
    4. add r3,r1,r2@r3=r1+r2
    5. ex:
    6. mov r1,#0XFFFFFFFE
    7. mov r2,#2
    8. addS r3,r1,r2@r3=r1+r2 @运算的结果影响到条件位
    9. 2.SUB
    10. mov r1,#0XFFFFFFFE
    11. mov r2,#2
    12. sub r3,r1,r2@r3=r1-r2
    13. ex2:
    14. mov r1,#0XFFFFFFFE
    15. mov r2,#2
    16. subs r3,r2,r1@r3=r2-r1
    17. 3.ADC
    18. mov r1,#0XFFFFFFFE
    19. mov r2,#2
    20. ADDS r3,r2,r1 @r3=r1+r2
    21. ADC R4,R2,#3 @R4=R2+3+cpsr(C位) 6
    22. 4.sbc:减法运算考虑条件位
    23. mov r1,#0XFFFFFFFE
    24. mov r2,#2
    25. SUBS r3,r2,r1 @r3=R2-R1 4
    26. sbC R4,R1,#3 @R4=R1-3-CPSR(C位取反)

    4.3 64位数据进行算数运算

    1. 原则:
    2. 一个 64位数保存在两个寄存器
    3. 32位运算,低32位运算
    4. mov r1,#0XFFFFFFFE @保存第一个数据的低32
    5. mov r2,#2@保存第一个数据的高32
    6. mov r3,#3 @保存第二个数据的低32
    7. mov r4,#4 @保存第2数据的高32
    8. @低32位运算要求影响条件位
    9. ADDS R5,R1,R3@R5保存运算后结果的低32
    10. ADC R6,R2,R4@R6寄存器保存运算结果的高32位,需要考虑条件位

    5.比较指令

    1. 格式:
    2. cmp 第一操作数,第二操作寄存器
    3. 比较两个数据
    4. cmp命令本质:实际上就是比较的两个数进行减法运算,并且减法运算的结果会影响到CPSR寄存器的条件位
    5. 通常比较指令完毕之后会使用条件码进行判断,根据判断的结果做不同的逻辑
    1. mov r1,#3
    2. mov r2,#4
    3. cmp r1,r2 @比较两个数
    4. SUBHI r3,r1,r2 @如果r1>r2 进行减法运算
    5. MULEQ r3,r1,r2@如果两数相等,进行乘法运算
    6. ADDCC R3,R1,R2@如果r1<r2 ,进行加法运算

    6. 跳转指令

    1. 格式:
    2. <opcode>{<cond>} 标签
    3. 功能:跳转到指定的标签下
    4. 指令码:
    5. b:跳转时不影响LR寄存器的值
    6. ex:.text
    7. .global _start
    8. _start:
    9. mov r1,#3
    10. mov r2,#4
    11. b fun1 @程序跳转
    12. mul r5,r1,r2
    13. stop:
    14. b stop
    15. fun1:
    16. add r4,r1,r2
    17. .end
    18. bl:跳转时影响LR寄存器的值
    19. .text
    20. .global _start
    21. _start:
    22. mov r1,#3
    23. mov r2,#4
    24. bl fun1 @程序跳转
    25. mul r5,r1,r2
    26. stop:
    27. b stop
    28. fun1:
    29. add r4,r1,r2
    30. mov pc,lr @程序返回
    31. .end

    7.单寄存器内存读写指令

    1. 向内存中写:
    2. str:向内存中写一个字(4字节)的数据
    3. strh:向内存写半个字(2字节)的数据
    4. strb:向内存写一个字节的数据
    5. 从内存读:
    6. ldr:从内存读取一个字的数据
    7. ldrh:从内存读取半个字的数据
    8. ldrb:从内存读取一个字节的数据
    1. mov r1,#0XFFFFFFFF
    2. ldr r2,=0X40000000
    3. @向内存写入
    4. str r1,[r2]
    5. @从内存读
    6. ldr r3,[r2]

    8.批量寄存器的内存读写方式

    1. mov r1,#1
    2. mov r2,#2
    3. mov r3,#3
    4. mov r4,#4
    5. mov r5,#5
    6. ldr r6,=0X40000000
    7. stm r6,{r1,r2,r3,r4,r5} @将r1-r6寄存器的值写道r6指向的连续内存中
    8. ldm r6,{r7,r8,r9,r10,r11}@从r6指向的连续内存中读取数据保存到r7-r11寄存器中

    四、栈内存读写

    1、栈的类型

    1. 增栈:压栈结束后,栈顶往地址大的方向增长
    2. 减栈:压栈结束后,栈顶往地址小的方向增长
    3. 空栈:压栈结束后,栈顶区域没有有效数据
    4. 满栈:压栈结束后,栈顶区域存放有效数据
    5. 空增栈(EA)/空减栈(ED)/满增栈(FA)/满减栈(FD)
    6. ARM使用的栈是满减栈

    2、满减栈压栈的出栈操作

    1. ex1
    2. ldr sp,=0X40000020 @指定顶地址
    3. mov r1,#1
    4. mov r2,#2
    5. mov r3,#3
    6. mov r4,#4
    7. mov r5,#5
    8. push {r1-r5} @压栈
    9. pop {r6-r10} @将栈顶元素数值出栈
    10. ex2:
    11. ldr sp,=0X40000020 @指定顶地址
    12. mov r1,#1
    13. mov r2,#2
    14. mov r3,#3
    15. mov r4,#4
    16. mov r5,#5
    17. STMDB sp!,{r1-r5} @压栈
    18. LDMIA sp!,{r6-r10} @将栈顶元素数值出栈
    19. EX3:
    20. ldr sp,=0X40000020 @指定顶地址
    21. mov r1,#1
    22. mov r2,#2
    23. mov r3,#3
    24. mov r4,#4
    25. mov r5,#5
    26. STMfd sp!,{r1-r5} @压栈
    27. LDMfd sp!,{r6-r10} @出栈
    28. 4.栈实例---叶子函数的调

    3、栈实践,叶子函数的调用过程

    1. .text
    2. .global _start
    3. _start:
    4. ldr sp,=0X40000020 @初始化栈
    5. b main
    6. main:
    7. mov r1,#1
    8. mov r2,#2
    9. bl func
    10. add r3,r1,r2
    11. b main
    12. func:
    13. @压栈保护现场
    14. stmfd sp!,{r1,r2}
    15. mov r1,#3
    16. mov r2,#4
    17. sub r4,r2,r1
    18. @出栈恢复现场
    19. ldmfd sp!,{r1,r2}
    20. mov pc,lr @返回main函数
    21. wh:
    22. b wh
    23. .end

    4、非叶子函数的调用过程

    1. .text
    2. .global _start
    3. _start:
    4. ldr sp,=0X40000020 @初始化栈
    5. b main
    6. main:
    7. mov r1,#1
    8. mov r2,#2
    9. bl func
    10. add r3,r1,r2
    11. b main
    12. func:
    13. @压栈保护现场
    14. stmfd sp!,{r1,r2,lr}
    15. mov r1,#3
    16. mov r2,#4
    17. bl fun1
    18. sub r4,r2,r1
    19. @出栈恢复现场
    20. ldmfd sp!,{r1,r2,lr}
    21. mov pc,lr @返回main函数
    22. fun1:
    23. @压栈保护现场
    24. stmfd sp!,{r1,r2}
    25. mov r1,#4
    26. mov r2,#5
    27. mul r5,r1,r2
    28. @出栈恢复现场
    29. ldmfd sp!,{r1,r2}
    30. mov pc,lr
    31. wh:
    32. b wh
    33. .end

  • 相关阅读:
    【python】函数的使用
    游戏初步——发牌程序(控制台版)以及一些扩展(python)
    【mybatis】mybatis面试题
    Redis实践
    异步复位同步释放与同步复位打拍
    基于SSM的概念可视化程序设计学习系统毕业设计源码021009
    Django的模板系统(一)
    Selinux
    RAID卡管理工具使用
    我赢助手详解抖音推荐算法的底层逻辑,视频是怎样从零开始到爆款的?
  • 原文地址:https://blog.csdn.net/Venusler/article/details/133585234