ARM指令
- 编绎执行下列汇编程序sy1.S,要示在开发板上执行。程序执行后返回到调用处,使用uboot的md 0x20009000 1命令查看0x20009000处的值。理解程序如何返回的调用处的,程序调用要做哪些工作。如果省去最后mov pc,lr指令,则会出现什么结果,为什么?
.text
.global _start
_start:
mov r0,#0x04
mov r1,#0x03
add r2,r0,r1
Ldr r3,=0x20009000
str r2,[r3]
mov pc,lr # 函数返回 下一题将会解释此条代码的作用
.end
- 将sy1程序下载到0x20007000处,编写汇编程序sy2.S,调用sy1,并能正确返回。
由于三级流水线:
所以当第七行指令执行时,pc已经指向到第十行指令。所以第一题函数将lr赋值给pc,即将pc重新指向第10行指令。
.global _start
_start:
ldr r0,=0x20007000
push {lr} # 保存lr
mov lr,pc
mov pc,r0
pop {lr}
mov pc,lr # 同上一题作用
.end
- 编写程序sy3.S,功能:开中断,禁止快速中断。
.global _start
_start:
# I F T M[4:0]
mrs r0,cpsr # 保存当前状态寄存器
bic r0,r0,#0x80 # 第8位清零
orr r0,r0,#0x40 # 逻辑或
msr cpsr,r0 # 还原当前程序状态寄存器
mov pc,lr
- 编写程序sy4.S,读取内存地址为0x20008000处的值入r0,修改r0低8位为0x1f 修改某几位的值可以采用,先置零,再逻辑或的方式,其他位保持不变。并将r0的值存入内存单元0x20009000处。
.global _start
_start:
ldr r1,=0x20008000 # r1赋值为
ldr r0,[r1] # 再从r1读取
bic r0,r0, #0xff # ro置零
orr r0,r0, #0x1f # 修改r0第八位为0x1f
ldr r1,=0x20009000
str r0,[r1]
mov pc,lr
- Sy5.S使用循环计算1+2+…+100 并将结果存入0x20009000处
.global _start
_start:
mov r0,#0
mov r1,#1
loop:
cmp r1,#100
bgt exit
add r0,r0,r1
add r1,r1,#1
b loop
exit:
ldr r1,=0x20009000
str r0,[r1]
mov pc,lr
.end
- 编写程序sy6.S计算 1+(1+2)+(1+2+3)+….+(1+2+..+20),并将结果存入0x20009000处,要编写子程序addn 计算1+2+..n,主程序调用该子程序最终完成计算( 结果: 0x604 )。
BL: 带链接的跳转。 首先将当前指令的下一条指令地址保存在LR寄存器,然后跳转的lable。通常用于调用子程序,可通过在子程序的尾部添加mov pc, lr 返回。
.global _start
_start:
mov r3,#0 // save sum
mov r4,#1 // count
push {lr}
for:
cmp r4,#20
bgt endfor
mov r0,r4
bl addn
add r3,r3,r0
add r4,r4,#1
b for
endfor:
ldr r0,=0x20009000
str r3,[r0]
pop {lr}
mov pc,lr
addn:
mov r1,#1 // count r0:refrence ,return value
mov r2,#0 //save result
loop:
cmp r1,r0
bgt exit
add r2,r2,r1
add r1,r1,#1
b loop
exit:
mov r0,r2
mov pc,lr
.end