GNU汇编语法和Cortex-A7常用汇编指令

GNU汇编语法

GNU汇编语法适用于所有架构,并不只被ARM独享,GNU语句的格式如下:

bash 复制代码
label: instruction @ comment
#label即标号,指的是地址位置,有些指令前面有标号,代表这个指令的地址
#任何以:作为结尾的标识符都会被识别为一个标号
#instruction指的是伪指令或者汇编指令
#comment表示注释
#ARM中的指令、伪指令、伪操作、寄存器名等可以全部使用大写,也可以全部使用小写,但是不能大小写混用

伪操作

.section:用户可以使用.section来定义一个段,语法格式:

bash 复制代码
.section .testsection @定义了一个testsection段

汇编系统也预先定义了一些段名,比如说:.text表示代码段,.data表示初始化的数据段,.bss表示未初始化的数据段,.rodata表示只读数据段。
其他

  1. .byte定义单字节数据,比如.byte 0x12
  2. .short定义双字节数据,比如.short 0x1234
  3. .long定义一个四字节数据,比如.long 0x12345678
  4. .equ赋值语句,格式为:.equ 变量名,表达式,比如说.equ num 0x12,表示num=0x12
  5. .align表示数据字节对齐,比如.align 4表示4字节对齐
  6. .end表示源文件结束
  7. .global定义一个全局符号,比如说.global _start
    函数
    GNU汇编支持函数:
bash 复制代码
函数名:
	函数体
	返回语句(不是必须的)
@举例
Undefined_Handler:
	ldr r0,=Undefined_Handler
	bx r0

Cortex-A7常用汇编指令

处理器内部数据传输指令

处理器内部来回传递数据,常见的操作有三个,第一个是将数据从一个寄存器传到另外一个寄存器,第二种是将数据从一个寄存器传到特殊寄存器,如CPSR和SPSR寄存器,第三种是将立即数传到寄存器里。
MOV指令:将源寄存器里的数据拷贝到目的寄存器里,或者将一个立即数传递到寄存器里。

bash 复制代码
MOV R0,R1 @将寄存器R1的数据传递给寄存器R0,即R0=R1
MOV R0,#0X12 @将立即数0X12传递给R0寄存器,即R0=0X12

MRS指令:用于将特殊寄存器里的数据传递给通用寄存器,要读取特殊寄存器里的数据只能使用MRS指令。

bash 复制代码
MRS R0,CPSR @将特殊寄存器CPSR里的数据传递给R0,即R0=CPSR

MSR指令:将普通寄存器的数据传递给特殊寄存器,写特殊寄存器只能使用MSR。

bash 复制代码
MSR CPSR,R0 @将普通寄存器的数据传递给通用寄存器,即CPSR=R0

存储器访问指令

ARM不能直接访问存储器,我们用汇编来配置IMX6UL的时候需要借助存储器访问指令,一般先将要配置的值写入到Rx寄存器中,然后借助存储器访问指令将Rx寄存器里的数据写入到存储器中,
LDR指令:LDR主要用于从存储器里加载数据到寄存器Rx中,也可以将一个立即数加载到寄存器Rx中,LDR加载立即数的时候要用=,而不是#,LDR最常用的场景就是读取一个寄存器里的数据了,比如说我们有个寄存器GPIO1_GPIR,地址为0X12345678,那么我们可以通过如下的方式读取寄存器的数据。

bash 复制代码
LDR Rd, [Rn , #offset]
bash 复制代码
LDR R0,=0X12345678 @将寄存器地址0X12345678加载到R0中
LDR R1,[R0]	@读取0X12345678位置的数据到R1中
#上述代码的offset为0

STR指令:STR主要用于把数据写入存储器中。

bash 复制代码
STR Rd, [Rn, #offset]
bash 复制代码
LDR R0,=0X12345678 @将寄存器的地址写入R0中
LDR R1,=0X87654321 @将要写入内存的数据写入R1中
STR R1,[R0] @将R1中的值写入R0保存的地址中

LDR和STR都是按照字写入数据的,如果需要按照字或者半字写入数据,可以在指令后面加入B或者H,比如说LDRB,LDRH,STRB,STRH。

压栈和出栈

C语言里经常在一个函数里调用另外一个函数,如果在调用函数A期间我们需要调用函数B,那么就要对函数A的现场进行保护,保存函数A的上下文,当函数B执行完之后,再恢复执行函数A时候的寄存器即可,现场保护需要用到入栈操作,恢复现场需要用到出栈操作。

PUSH:将寄存器列表存入栈中,假设我们现在要将R0~R3和R12寄存器压入堆栈里,处理器的堆栈是向下生长的。

bash 复制代码
PUSH {R0~R3,R12} @将R0~R3,R12压栈
#还有一种写法
STMFD SP!,{R0~R3,R12}


POP:从栈中恢复寄存器列表,如果我们要出栈的话可以使用如下代码。

bash 复制代码
POP {R0~R3,R12}
#还有另外一种写法
LDMFD SP!,{R0~R3,R12}

出栈的位置是栈顶,也就是SP指针当前的位置,向上增长。

跳转

B指令:B指令会将PC寄存器里的值设置为目标跳转地址,一旦执行B指令,ARM处理器就会立刻跳转到目标地址,如果不再返回原来的位置,就可以使用B指令。

bash 复制代码
_start:
	ldrsp,=0x80200000 @设置栈顶指针
	b main @跳转到main函数

BL指令:BL指令在跳转之前会在LR中保存当前PC寄存器的值,所以可以将LR寄存器里的值重新加载到PC中跳转到之前的代码继续运行。

bash 复制代码
push {R0,R1}
cps #0x13 @允许中断再次进去
bl system_irqhandler @加载C语言中断程序到R2寄存器里
cps #0x12 @进入irq模式
pop {R0,R1}
str R0,[R1,#0X10] @中断执行完成

运算符指令

算数运算

逻辑运算

相关推荐
Moonbit2 小时前
MoonBit Pearls Vol.13: 使用 MoonBit 开发一个 HTTP 文件服务器
服务器·后端·http
云飞云共享云桌面2 小时前
三维设计办公资源如何共享集中和安全管控?
运维·服务器·数据库·安全·自动化·制造
资料,小偿3 小时前
4.95基于8086流水灯霓虹彩灯控制器,8086彩灯控制器proteus8.9仿真文件+源码功能四个开关对应四种模式。
汇编·proteus
yuanManGan4 小时前
走进Linux的世界:进程优先级
linux·运维·服务器
一叶知秋yyds4 小时前
linux 系统查看进程占用物理内存大小方法
linux·运维·服务器
AI绘画小334 小时前
渗透测试数据库判断卡壳?分类 + 方法 + SQL/NoSQL 脚本速用
服务器·数据库·sql·mysql·web安全·nosql
尤利乌斯.X4 小时前
在Java中调用MATLAB函数的完整流程:从打包-jar-到服务器部署
java·服务器·python·matlab·ci/cd·jar·个人开发
Bowen_CV5 小时前
Linux 系统安装与环境配置实践
linux·运维·服务器
无泊里6 小时前
linux:系统用户命令
linux·运维·服务器