ARM64的汇编器
(1)ARM公司官方的汇编器;
(2)GNU AS汇编器:aarch64-linux-gnu-as;
(3)gcc采用as作为汇编器,所以汇编码是AT&T格式;
(4)AT&T格式:源于贝尔实验室;
(5)ARM格式:ARM官方汇编语法;
汇编语法
(1)label:任何以冒号结尾的标识符,都被认为是一个标号;
(2)注释:
“//”,注释
“#”,在一行的开始,注释整行;
(3)指令、伪指令、寄存器,可以全部大写或者小写,GNU默认风格是小写;
(4)Symbol:代表它所在的地址,也可以当作变量或者函数来使用;
全局symbol, 可以用.global声明;
局部symbol, 局部范围使用,开头以0-99为标号,通常和b指令结合使用
f:告诉编译器向前搜索;
b:告诉编译器向后搜索;
伪指令
(1).glign对齐,填充数据实现对齐。ARM64系统中,第一个参数表示2^n大小;
(2)数据定义伪指令
伪指令 |
描述 |
.byte |
把8位数当作数据插入汇编中 |
.hword |
把16位数当作数据插入汇编中 |
.long和.int |
把32位数当作数据插入汇编中 |
.quad |
把64位数当作数据插入汇编中 |
.float |
把浮点数当作数据插入汇编中 |
.ascii “string” |
把string当作数据插入汇编中,末尾需手动添加’\0’ |
.asciz “string” |
类似.ascii,在string后自动插入一个’\0’ |
.rept |
重复定义 |
.equ |
赋值操作 |
.set |
赋值操作 |
函数相关伪操作
伪指令 |
描述 |
.global |
定义一个全局的符号 |
.include |
引用头文件 |
.if, .else, .endif |
控制语句 |
if语句 |
|
.ifdef symbol .ifndef symbol .ifc string1,string2 .ifeq expression .ifeqs string1,string2 .ifge expression .ifle expression .ifle expression<.ifne expression> |
判断symbol是否有定义 判断symbol是否没定义 判断字符串是否相等 判断exp是否为0 等同于.ifc exp是否大于等于0 exp是否小于等于0 exp是否不等于0 |
与段相关的伪指令
(1).section:表示接下来的汇编会链接到哪个段里,如代码段、数据段等
每一个段都以段名开始,以下一个段名或文件结尾结束
“flags”,表示段的属性,可写,可执行等;
(2).pushsection:把下面代码push到指定section中;
.popsection:技术push,成对使用;
仅仅是把pushsection/.popsection之间的代码,加载到指定section中,其他不变;
实例1:使用伪指令,实现一个类似linux内核中表的定义;
宏
(1).macro和.endm组成一个宏;
(2).macro后面跟着的依次是宏名称,宏参数;
(3)在宏中使用参数,需要添加前缀"";
(4)红参数定义时,可以设置初始值
(5)宏可以使用空格
(6)使用"()"表示字符串结束
练习2:
ARM64编译选项
-EB:用于大端模式的CPU, -EL表示小端模式;
-mabi:指定ABI模式,ilp32表示elf32, lp6表示ELF64,默认lp64;
-mcpu=processor+extension: 指定CPU型号,比如cortex-a72;
-march=,用于指定架构,比如armv-8.2-a;
特殊字符
“//”注释
“#”: 在一行开头,注释一行;还可以表示立即数;
“#:lo12”:表示地12位;
“ldr”:伪操作;
ARM64特有的伪操作;
.bss:切换到bss段;
.dword/.xword:64位数据;
name .reg register_name:为寄存器创建别名;