文章目录
1,逻辑指令
and r0,r1,#0xFF // r0 = r1&0xFF
orr r3,r0,#0x0F // r3 = r0|0x0F
bic r0,r0,#0x03 // 清除r0中的0号位和1号位
tst r0,#0x20 //测试第6位是否为0 ,为0则Z标志置1 (实际上是逻辑与操作)
cmp r1,r0 //将R1与R0相减做比较,并根据结果设置CPSR的标志位
1.1例
使能中断和快速中断?
mrs r0,cpsr
bic r0,r0,#0xc0
msr cpsr,r0
判断当前工作状态是否是ARM状态,是则切换到user 工作模式?
mrs r0,cpsr
tst r0,#0x20
andeq r0,r0,#0xFFFFFFE0 @将低五位模式位清零
orreq r0,r0,#0x10 @将低五位模式位设置成10000
msreq cpsr,r0
2,算数指令
add r0,r1,r2 //r0=r1+r2
sub r0,r1,#3 //r0= r1 - 3
sub r0,r1,r2,LSL#1 //先把r2左移一位
mul r1,r2,r3 //r1=r2*r3
3,跳转指令
b main //跳转到标号为main地代码处
bl func //保存下一条要执行的指令的位置到 LR寄存器,跳转函数func
//当跳转代码结束后,用MOV PC,LR指令跳回来
beq addr //当CPSR寄存器中的Z条件码置位时,跳转到该地址处
bne addr //当不等时,跳转到地址addr
3.1.1例
用汇编实现下面功能
void main(void)
{
int ret=0;
func1(2);
while(1) {};
}
func1(int a)
{
if(a==2)
return func2(a);
else
return func3(a);
}
func2(int a)
{
return a+3;
}
func3(int a)
{
return a-1;
}
.text
main:
mov r5,#0
mov r0,#3
bl func1
main_end:
b main_end
func1:
mov r8,lr @备份lr寄存器中的地址
cmp r0,#2
bleq func2
blne func3
mov pc,r8
func1_end:
func2:
add r0,r0,#3
mov pc,lr
func2_end:
func3:
sub r0,r0,#1
mov pc,lr
func3_end:
.end
3.1.2例
实现 延时1秒函数
@delay fos 1 second
delay1s:
ldr r4,=0x24f000
loop_delay1s:
sub r4,r4,#1
cmp r4,#0
bne loop_delay1s
delay1s_end:
mov pc,lr
3.1.3例
用汇编实现求最大公约数?(如9 15 值是3)
int GCD(int a,int b)
{
while(1)
{
if(a==b)
break;
if(a>b){
a=a-b;
}else{
b=b-a;
}
}
return a;
}
.text
main:
mov r0,#9
mov r1,#15
bl gcd
main_end:
b main_end
gcd:
loop_gcd:
cmp r0,r1
beq gcd_end
subgt r0,r0,r1
sublt r1,r1,r0
b loop_gcd
gcd_end:
mov pc,lr
4,Load/Store 指令
注:load/store架构规定,存储器之间不能直接拷贝,需通过寄存器做中转
ldr r0,[r1] (load) //r0=*r1 r1里存放的是地址,把该地址里存放的内容读入到r0中
//LDRB(byte) LDRH(half word)
ldr r0,[r1,#8] //r0=*(r1+8) 存储器地址为r1+8的字数据读入寄存器0。
ldr pc,_irq // pc = *(_irq) 将标号中的内容放入pc中
str r0,[r1] (store) // *r1 = r0 将寄存器r0中值写入到存储器地址为r1的空间中
str r0,[r1],#4 // r0=*r1, r1=r1+4 将r0 中的字数据写入以r1为地址的内存中,并将新地址r1+4 写入r1
str r0,[r1,#4] //*(r1+4)=r0 将r0 中的字数据写入以r1+4 为地址的内存中
4.1 前索引/后索引
4.2.1,例—代码
.text @代码段
main:
ldr r5,=buf @伪指令
ldr r0,[r5] @load指令,将r5中的地址所对应的内容(字),放入r0中
ldrb r1,[r5] @load指令,将r5中的地址所对应的内容(字节),放入r0中
ldrh r2,[r5],#4 @load指令,将r5中的地址所对应的内容(半字),放入r0中。之后将r5中的地址向后偏移4
ldr r3,[r5],#-4 @load指令,将r5中的地址所对应的内容(字),放入r0中。之后将r5中的地址向前偏移4
ldr r6,=dest_buf1
ldr r7,=dest_buf2
ldr r8,=dest_buf3
str r0,[r6]
str r1,[r7]
strb r2,[r8]
main_end:
b main_end
.data @数据段
buf: .byte 0x01,0x02,0x03,0x04 @相当于C语言中的数组,char buf[]={0x01,0x02,0x03,0x04}
dest_buf1: .space 4 @相当于C语言中的数组,char buf[4]
dest_buf2: .space 4 @相当于C语言中的数组,char buf[4]
dest_buf3: .space 8 @相当于C语言中的数组,char buf[8]
.end @程序结束
4.2.2,例—运行结果
4.3,例
用汇编实现下面功能
main()
{
int i=0;
const char buf[]={1,2,3};
char destBuf[8];
for(i=0,i<3,i++)
{
destBuf[i] = buf[i];
}
}
.text @代码段
main:
ldr r6,=buf
ldr r7,=dest_buf
mov r5,#0
loop:
cmp r5,#3
beq main_end
ldrb r0,[r6],#1
strb r0,[r7],#1
add r5,r5,#1
b loop
main_end:
b main_end
buf: .byte 1,2,3
.data @数据段
dest_buf: .space 3
.end @代码结束
5,GNU伪指令
.text 将定义符开始的代码编译到代码段
.data 将定义符开始的代码编译到数据段
.end 文件结束
.equ GPG3CON, 0XE03001C0 定义宏(即用GPG3CON代替 0XE03001C0)
.byte 定义变量 1字节
.byte 0x11,'a',0 定义字节数组
.word 定义word变量 (4字节 32位机)
.word 0x12344578,0x33445566
.string 定义字符串 .string "abcd