ARMGNU伪指令

摘要:
endm之间的指令序列称为宏定义体。当地址值为16字节对齐时,值范围更大。此指令等效于添加、pc、offsetADRADRL。ADRL<reg><label>LDR加载一个32位常量和一个地址寄存器LDRreg,=exprreg:目标寄存器expr:32位常量表达式。

符号定义伪指令

.global,.local,.set,.equ

.global

使得符号对连接器可见,变为对整个工程可用的全局变量

.global symbol

.local

表示符号对外部不可见,只对本文件可见

.local symbol

.set

给一个全局变量或局部变量赋值,和.equ的功能一样

.set symbol expr
.set start, 0x40
.set start, 0x50
mov r1, #start      ;r1里面是0x50

.equ

.set一样,只是格式不同

symbol .equ  expr
start  .equ, 0x40
start  .equ, 0x50
mov r1, #start      ;r1里面是0x50

数据定义伪指令

.byte,.short,.long,.quad,.float,.string,.asciz,.ascii,.rept

.byte

在存储器中分配1个字节,用指定的数据对存储单元进行初始化

label:  .byte   expr    ;label是程序标号,expr可以是-128~255的数字,也可是字符
a:  .byte   #1  ;等价于C中的char a=1;

.short

在存储器中分配2个字节,用指定的数据对存储单元进行初始化

a: .short 0x1234

.word / .long

在存储器中分配4个字节,用指定的数据对存储单元进行初始化

a: .word 0x12345678

.long

在存储器中分配个字节,用指定的数据对存储单元进行初始化

.quad

在存储器中分配8个字节,用指定的数据对存储单元进行初始化

a: .quad 0x12345678 ;等价于C中的long a=0x1234567812345678

.float

在存储器中分配4个字节,用指定的浮点数据对存储单元进行初始化

a: .float 1.11

.space/.skip

用于分配一块连续的存储区域并初始化为指定的值,如果后面的填充值省略不写则在后面填充为0;

label: .space size,expr     ;expr可以是4字节以内的浮点数 
a:  space 8, 0x1

.string

定义一个字符串,默认是string8,还有string16,string32,string64

a: .string "hello world!"

.rept

重复执行接下来的指令,以.rept开始,以.endr结束

.rept cnt   ;cnt是重复次数
...
.endr

汇编控制伪操作

流程控制伪指令主要yy.if .else .endif.macro .endm .exitm

.if .else .endif

.if logical-expression
...
.elseif logical-expression2
...
.else
...
.endif

.macro .endm .exitm

该伪指令可以将一段代码定义为一个整体,称为宏指令,然后就可以在程序中通过宏指令多次调用该段代码,而.exitm指令用来退出当前的宏指令,宏指令可以使用一个或多个参数,当宏操作被展开时,这些参数被相应的值替换。
包含在.macro。endm之间的指令序列称为宏定义体。在宏定义体的第一行应声明宏的原型,包含宏名所需的参数,然后就可以在汇编程序中通过宏名来调用该指令序列,在源程序被编译时,汇编器将宏调用展开,用宏定义中的指令序列代替程序中的宏调用,并将实际参数的值传递给宏定义中的形式参数

.macro macroname macargs ...
;code
.endm

杂项

.align	    用于使程序当前位置满足一定的对齐方式
.section	用来定义一个段的伪指令
.data		用来定义一个数据段
.text		用来定义一个代码段
.include	用来包含一个头文件	
.arm		定义以下代码使用arm指令集编译
.code 32	同.arm
.code 16	同.thumb
.thumb		定义以下代码使用thumb指令集编译
.extern 	用于声明一个外部符号,用于兼容性其他汇编
.weak		用于声明一个弱符号,如果这个符号没有定义,编译就忽略,而不会报错
.end		表示汇编结束

ADR

把标签所在的地址加载到寄存器中,这个指令将基于PC相对偏移的地址值或基于寄存器相对偏移的地址值读取到寄存器中。当地址值是字节对齐的时候,取值范围是-255255B;当地址值是字对齐的时候,取值范围为-10201020B。当地址值是16字节对齐时,取值范围更大。 该指令等价于add <reg>, pc , offset

ADR <reg> <label>

ADRL

用于将中等范围地址读取到寄存器中

ADRL <reg> <label>

LDR

装载一个32位的常数和一个地址寄存器

LDR reg, =expr

reg:目标寄存器
expr:32位常量表达式。汇编器根据expr的取值情况,对LDR伪指令做如下处理:

  1. 当expr表示的指令地址值没有超过MOV指令或MVN指令的地址取值范围时,汇编器用一对MOV和MVN代替LDR指令
  2. 当超过了的时候,汇编器将常数放入缓存吃,同时用一条基于PC的LDR读取该常数
LDR R3,=0xff0
;将常熟0xff0读到内存中相当于MOV R3, #0xff0

LDR R1,=0xfff   
;将常数0xfff读到内存,
;相当于LDR R1,[pc, offset_to_litpool]  ... litpool DCD 0xfff

LDR R2, =place  
;将place标号的地址读入到R1中
;相当于LDR R1,[pc, offset_to_litpool]  ... litpool DCD place

免责声明:文章转载自《ARMGNU伪指令》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇cors 处理OPTIONS verb开源中国社区项目部署下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux中的汇编简介

GNU as汇编语法 GNU汇编语法使用的是AT&T汇编它和Intel汇编的语法主要有以下一些不同: AT&T汇编中的立即操作数前面要加上'$',寄存器操作数名前要加上百分号'%',绝对跳转操作数前要加上'*',Intel的语法均不包含这些符号; AT&T语法与Intel语法中使用的源操作数和目的操作数顺序正好相反,AT&...

C++ 构造和析构

1、继承关系可认为,子类在父类的基础上进行。从这个角度讲,可把它认为穿衣脱衣的过程。穿衣是:先穿内衣,再穿外套。脱衣是:先脱外套,在脱内衣。构造是:先调用父类构造方法,再调用子类构造方法。析构是:先调用子类析构方法,再调用父类析构方法。 2、构造可分为两个步骤:初始化列表和方法内赋值。前者的使用场景是:初始化,即copy构造。后者的使用场景是:赋值,即co...

mnesia数据库学习笔记二

  mnesia数据库学习笔记二 创建一个mnesia数据库 定义方案 数据模型 启动Mnesia 创建新表 1、定义方案(schema) Mnesia 系统配置是在Schema中描述的。Schema数据表中的数据只能通过其相关函数进行访问和修改。Mnesia允许动态配置其内容。 方案函数 mnesia:create_schema(NodeList)该...

Debug 和 Release 编译方式的本质区别

一、Debug 和 Release 编译方式的本质区别       Debug 通常称为调试版本,它包含调试信息,并且不作任何优化,便于程序员调试程序。Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用。       Debug 和 Release 的真正秘密,在于一组编译选项。下面列出了分别...

spring的后置处理器——BeanPostProcessor以及spring的生命周期

后置处理器的调用时机 BeanPostProcessor是spring提供的接口,它有两个方法——postProcessBeforeInitialization、postProcessAfterInitialization。关于这两个方法的调用时机,可以参考spring源码注释。 /** * Apply this BeanPostProc...

StringBuilder 以及 StringBuffer默认大小与扩容

默认值初始化: 1.  首先明确 StringBuffer类与 StringBuilder类均继承了抽象类 AbstractStringBuilder类 无参构造方法 2. 源码中StringBuffer类和StringBuilder类初始化均调用父类的构造方法: 父类初始化: 子类默认传入值16 给父类初始化字符数组   有参构造方法:   扩容...