ARM汇编框架
xx.s
.text @表示当前为代码段 .global _start @将_start定义成全局符号 _start: @汇编的入口 MOV R1,#1 MOV R2,#2 MOV R3,#3 .end @汇编的结束
ARM汇编概述
汇编中的符号
- 指令:能够编译成一条32位的机器码,并且能被CPU识别和执行。
- 伪指令:本身不是指令,编译器可以将其替换成若干条指令
- 不会生成指令,只是在编译阶段告诉编译器怎么编译,类似C语言的条件编译
ARM的指令
- 数据处理指令:进行数学运算、逻辑运算
- 跳转指令:实现程序的跳转,本质就是修改PC寄存器
- Load/Store指令:访问(读写)内存
- 状态寄存器传送指令:用于访问(读写)CPSR寄存器
- 软中断指令:触发软中断
- 协处理器指令:操作协处理器的指令
指令基本格式
<操作码> <目标寄存器>, <第一操作寄存器>, <第二操作数>
ARM指令集
数据处理指令
.text .global _start _start: @ 数据搬运指令 MOV R1,#1 @把一个数搬运到一个寄存器 MOV R2,R1 @从一个寄存器搬运到另一个寄存器 MVN R0,#0xFF @按位取反再搬运 @ MOV PC,#0 @搬运一个数到PC寄存器,程序会跳转 @ 立即数,本质是包含在指令中的数,属于指令的一部分 @ 所以立即数不能太大,范围在0-255之间。 @ MOV R0, #0x12345678 @0x12345678这不是立即数,不能被编译成功 @ 0xFFFFFFFF这不是立即数,但是能被编译成功 @ 这一条是伪指令,编译器会把他替换成同样效果的指令。 MOV R0, #0xFFFFFFFF @ MVN R0,#0x00 @ 加法指令 ADD R3,R1,R2 @ R3 = R1 + R2 ADD R3,R2,#5 @ R3 = R2 + 5 @ 不合法的指令 @ ADD R3,#5,R2 @第一寄存器不能放数 @ 减法指令 SUB R1,R2,R3 @ R1 = R2 - R3 RSB R1,R2,#3 @ R1 = 3 - R2 逆向减法指令 @ 乘法指令 MUL R1,R2,R3 @ R1 = R2 * R3 @ 按位与 AND R1,R2,R3 @ R1 = R2 & R3 @ 按位或 ORR R1,R2,R3 @ R1 = R2 | R3 @ 按位异或 EOR R1,R2,R3 @ R1 = R2 ^ R3 @ 移位 LSL R1,R2,R3 @ R1 = R2 << R3, R2左移R3位,给R1 LSR R1,R2,R3 @ R1 = R2 >> R3, R2右移R3位,给R1 @ 位清零 BIC R1, R2, #0xF @ 第二操作数(0xF)中的哪一位,就将第一操作寄存器中的哪一位清零,然后放入目标寄存器 @ 数据运算指令的格式扩展 MOV R1,R2,LSL #1 @ R1 = (R2 << 1) @ 数据运算指令对条件位的影响,CPSR NZVC @ 默认情况下数据运算不会对条件为产生影响,当指令加后缀S后可以影响 MOV R1,#3 SUBS R2,R1,#5 @ 两个64位的数据做加法运算 @ 0x00000001 FFFFFFFF @ 0x00000002 00000005 MOV R1,#0xFFFFFFFF MOV R2,#0x00000001 MOV R3,#0x00000005 MOV R4,#0x00000002 ADDS R5,R1,R3 @溢出时条件位溢出位会自动置1 ADC R6,R2,R4 @ R6 = R2 + R4 + 'C',在执行的过程中,会把条件位的溢出位加上 @ 带借位的减法指令 @ 0x00000002 00000001 @ 0x00000001 00000005 MOV R1,#0x00000001 MOV R2,#0x00000002 MOV R3,#0x00000005 MOV R4,#0x00000001 SUBS R5,R1,R3 SBC R6,R2,R4 @ 本质: R6 = R2 - R4 - '!C',即执行的过程中,会把条件位的溢出位取反再减 stop: B stop .end
跳转指令
.text .global _start _start: @ 方式一:直接去修改PC寄存器的值 @ MOV R1,#1 @ MOV R2,#2 @ MOV R3,#3 @ MOV PC,#0x18 @ MOV R4,#4 @ 这条指令被跳过 @ MOV R6,#6 @ 方式二:通过跳转指令B @ 本质也是修改PC @ MOV PC,LR 跳转失败,它会跳转回:跳转指令,因为B跳转指令,没有保存返回地址给LR @MAIN: @ MOV R1,#1 @ B FUNC @ MOV R2,#2 @ MOV R3,#3 @FUNC: @ MOV R4,#4 @ MOV PC,LR @ 方式三:通过跳转指令BL @ 跳转的同时,会修改CPSR的跳转状态位的值,并且保存返回的地址给LR MAIN: MOV R1,#1 MOV R2,#2 BL FUNC MOV R3,#3 MOV R4,#4 FUNC: MOV R5,#5 MOV PC,LR stop: B stop .end
ARM条件码(不算指令)
@条件码 .text .global _start _start: MAIN: MOV R1,#1 MOV R2,#1 @比较指令 CMP R1,R2 @没有目标寄存器,结果自动存储在状态寄存器CPSR的NZCV @本质就是一条减法指令,SUBS,只是没有将运算的结果存入寄存器 @如果R1==R2,Z=1,产生0 @如果R1!=R1,Z=0 @如果R1<R2,Z=0且C=0,产生了借位 @如果R1<=R2,C=0或Z=1 @如果R1>R2,C=1且Z=0 @如果R1>=R2,C=1或Z=1 BEQ FUNC @EQ是一个条件码助记符后缀,大多数指令都可以加后缀 MOV R3,#3 @该条指令会被跳过 FUNC: MOV R4,#4 @程序会跳转到这里 .end
ARM条件码和助记符后缀
ARM内存访问指令
内存访问指令1
@内存访问指令 .text .global _start _start: @ 写内存 MOV R1,#0xFFFFFFFF MOV R2,#0x40000000 @0x40000000 是可读可写的内存地址 @STR R1,[R2] @把R1寄存器中的数据存储到R2指向的内存空间4个字节 STRB R1,[R2] @把R1寄存器中的数据存储到R2指向的内存空间 @ 读内存 LDR R3,[R2] @把R2指向的内存空间的数据读取到R3 .end
ARM指令的寻址方式
@ ARM寻址方式 .text .global _start _start: @ 方式一:立即寻址 @ 回顾一下立即数,立即寻址即直接使用指令机器码中的立即数 MOV R1,#1 ADD R1,R2,#1 @ 方式二:寄存器取址 ADD R1,R2,R3 @ 方式三:寄存器移位寻址 MOV R1,R2, LSL #1 @ 方式四:寄存器间接寻址 STR R1, [R2] @...还有很多,ARM一共九种 .end
内存访问指令2
@ 内存访问指令2 @ 基于ARM指令的寻址方式 @ 基址加变址寻址 .text .global _start _start: MOV R1, #0xFFFFFFFF MOV R2, #0x40000000 MOV R3, #4 @ 前索引: @STR R1, [R2,#4] @ 将R1寄存器中的数据写入到R2+4指向的内存空间:0x40000004 @ R2的值并不会改变,对比自动索引 @STR R1, [R2,R3] @ 将R1寄存器中的数据写入到R2+R3指向的内存空间:0x40000004 @STR R1, [R2,R3,LSL #1] @ 将R1寄存器中的数据写入到R2+(R3<<1)指向的内存空间:0x40000008 @***************************************************************** @ 后索引: STR R1, [R2], #8 @ 将R1寄存器中的数据写入到R2指向的内存空间:0x40000000 @ 然后R2自增8 @ 自动索引: STR R1, [R2,#8]! @ 将R1寄存器中的数据写入到R2+8指向的内存空间:0x40000008 @ 然后R2自增8 .end
END
原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/245367.html