嵌入式linux-ARM体系结构及接口技术,ARM汇编指令,逻辑指令,算数指令,跳转指令,load/

2019-07-12 18:33发布

文章目录

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