当前位置:首页 > 编程笔记 > 正文
已解决

国庆假期作业6

来自网友在路上 151851提问 提问时间:2023-10-05 20:37:07阅读次数: 51

最佳答案 问答题库518位专家为你答疑解惑

一、ARM的工作模式

1、非特权模式

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

2、特权模式

        异常模式:

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

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

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

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

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

        非异常模式:

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

二、汇编语言的相关语法

1、汇编语言的组成部分

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

2.汇编指令的介绍

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

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

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

三、汇编指令

1.数据搬移指令

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

2、移位指令

2.1 格式以及指令码

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

2.2 示例

1.左移mov r0,#0XFFlsl r1,r0,#0X4  @将R0的值左移4位保存在r1寄存器  R1结果:0XFF02.右移mov r0,#0XFF
lsr r1,r0,#0X4  @将R0的值右移4位保存在r1寄存器  R1结果:0XF
3.循环右移
mov r0,#0XFF
ror r1,r0,#0X4  @将R0的值循环右移4位保存在r1寄存器  R1结果:0XF000000F
4.c风格写法
mov r0,#0XFF
ror r1,r0,#(0X1<<2)  @将R0的值循环右移4位保存在r1寄存器  R1结果:0XF000000F

3.位运算指令

3.1 格式以及功能码

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

3.2 示例

1.and:
mov r0,#0XFFand r1,r0,#0XF0  @R1结果为0XF02.ORR:mov r0,#0XFForr r1,r0,#0XF000  @R1结果为0XF0FF
3.EOR:ldr r0,=0xf0f0EOr r1,r0,#0XFF  @R1结果为0XF00F
0000 0000 0000 0000 0000 0000 1111 1111
0000 0000 0000 0000 1111 0000 1111 0000
结果:0000 0000 0000 0000 1111 0000 0000 1111 -》0XF00F4.BICldr r0,=0xFFBIC r0,r0,#(0x1<<5)  @将R0的值第5位清0 @R0结果为0XDF

3.3 练习

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

4.算数运算指令

4.1 格式以及指令码

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

4.2 示例

1.ADD:加法ex1:  mov r1,#1mov r2,#2add r3,r1,r2@r3=r1+r2ex:mov r1,#0XFFFFFFFEmov r2,#2addS r3,r1,r2@r3=r1+r2  @运算的结果影响到条件位
2.SUBmov r1,#0XFFFFFFFEmov r2,#2sub r3,r1,r2@r3=r1-r2ex2:mov r1,#0XFFFFFFFEmov r2,#2subs r3,r2,r1@r3=r2-r1 
3.ADC
mov r1,#0XFFFFFFFE
mov r2,#2ADDS r3,r2,r1 @r3=r1+r2 ADC R4,R2,#3  @R4=R2+3+cpsr(C位)  6 4.sbc:减法运算考虑条件位
mov r1,#0XFFFFFFFEmov r2,#2SUBS r3,r2,r1 @r3=R2-R1    4sbC R4,R1,#3  @R4=R1-3-CPSR(C位取反)

4.3 64位数据进行算数运算

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

5.比较指令

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

6. 跳转指令

格式:
<opcode>{<cond>} 标签
功能:跳转到指定的标签下指令码:
b:跳转时不影响LR寄存器的值ex:.text
.global  _start_start:mov r1,#3mov r2,#4b fun1 @程序跳转mul r5,r1,r2stop:b stop  fun1:add r4,r1,r2.endbl:跳转时影响LR寄存器的值.text
.global  _start_start:mov r1,#3
mov r2,#4bl fun1 @程序跳转mul r5,r1,r2stop:b stop  fun1:add r4,r1,r2mov pc,lr @程序返回.end

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

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

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

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

四、栈内存读写

1、栈的类型

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

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

ex1:ldr sp,=0X40000020 @指定顶地址mov r1,#1mov r2,#2mov r3,#3mov r4,#4mov r5,#5push {r1-r5} @压栈pop {r6-r10}  @将栈顶元素数值出栈
ex2:ldr sp,=0X40000020 @指定顶地址mov r1,#1mov r2,#2mov r3,#3mov r4,#4mov r5,#5STMDB sp!,{r1-r5} @压栈LDMIA sp!,{r6-r10}  @将栈顶元素数值出栈
EX3:ldr sp,=0X40000020 @指定顶地址mov r1,#1mov r2,#2mov r3,#3mov r4,#4mov r5,#5STMfd sp!,{r1-r5} @压栈LDMfd sp!,{r6-r10}  @出栈
4.栈实例---叶子函数的调

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

.text  
.global _start _start:ldr sp,=0X40000020 @初始化栈b main
main:mov r1,#1mov r2,#2bl funcadd r3,r1,r2b mainfunc:
@压栈保护现场stmfd sp!,{r1,r2}mov r1,#3mov r2,#4sub r4,r2,r1@出栈恢复现场ldmfd sp!,{r1,r2}mov pc,lr  @返回main函数wh: b wh  .end 

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

.text  
.global _start _start:ldr sp,=0X40000020 @初始化栈b main
main:mov r1,#1mov r2,#2bl funcadd r3,r1,r2b mainfunc:
@压栈保护现场stmfd sp!,{r1,r2,lr}mov r1,#3mov r2,#4bl fun1sub r4,r2,r1@出栈恢复现场ldmfd sp!,{r1,r2,lr}mov pc,lr  @返回main函数
fun1:
@压栈保护现场stmfd sp!,{r1,r2}mov r1,#4mov r2,#5mul r5,r1,r2@出栈恢复现场ldmfd sp!,{r1,r2}mov pc,lrwh: b wh  .end 

查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"国庆假期作业6":http://eshow365.cn/6-15965-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!