Blog icon indicating copy to clipboard operation
Blog copied to clipboard

aarch64体系结构与编程2--GNU AS汇编器介绍

Open jason--liu opened this issue 4 years ago • 0 comments

Arm64的汇编器

  • ARM公司官方的汇编器
  • GNU AS汇编器:aarch64-linux-gnu-as
  • gcc采用as作为其汇编器,所以汇编码是AT&T格式的
  • AT&T格式:源自贝尔实验室,为开发UNIX系统而产生的汇编语法
  • ARM格式:arm官方汇编语法

gas汇编器语法

  • label: 任何以冒号结尾的标识符都被认为是一个标号
  • 注释:
    • “//” 表示注释
    • “#”:在一行的开始,表示注释整行
  • 指令,伪指令,寄存器,可以全部是大写或者小写,GNU风格默认是小写
  • Symbol:代表它所在的地址, 也可以当作变量或者函数来使用
    • 全局symbol,可以使用.global来声明
    • 局部symbol,主要在局部范围内使用,开头以0-99直接的数字为标号名,通常和b指令结合使用
    • f:指示编译器向前搜索
    • b:指示编译器向后搜索

例如

.global my_memory_test
my_memory_test:
    mov x1, 0x80000
    mov x2, 0x200000
    add x3, x1, 32
1: 
    ldr x4, [x1], #8 
    str x4, [x2], #8 
    cmp x1, x3
    b.cc 1b

    ret

汇编器常用伪指令

对齐伪指令

.align 对齐,填充数据来实现对齐。可以填充0或者使用nop指令。

  • 告诉汇编程序, align后面的汇编必须从下一个能被2^n整除的地址开始分配
  • ARM64系统中,第一个参数表示2^n大小。

数据定义伪指令

  • .byte: 把8位数当成数据插入到汇编中
  • .hword: 把16位数当成数据插入到汇编中
  • .long 和 .int:把32位数当成数据插入到汇编中
  • .quad: 把64位数当成数据插入到汇编中
  • .float: 把浮点数当成数据插入到汇编中
  • .ascii “string” -> 把string当作数据插入到汇编中,ascii伪操作定义的字符串需要自行添加结尾字符'\0'
  • .asciz “string” -> 类似ascii,在string后面插入一个结尾字符’\0’。
  • .rept:重复定义, 比如重复3次 image
  • .equ: 赋值操作
  • .set : 赋值操作

比如.equ abcd, 0x45 //让abcd 等于 0x45

函数相关的伪操作

  • .global:定义一个全局的符号
  • .include: 引用头文件
  • .if,.else, .endif 控制语句

if语句

  • .ifdef symbol 判断symbol是否定义
  • .ifndef symbol 判断symbol是否没有定义
  • .ifc string1,string2 字符串string1和string2是否相等
  • .ifeq expression 判断expression的值是否为0
  • .ifeqs string1,string2 等同于.ifc
  • .ifge expression 判断expression的值是否大于等于0
  • .ifle expression 判断expression的值是否小于等于0
  • .ifne expression 判断expression的值是否不为0

与段相关的伪操作

  • .section:表示接下来的汇编会链接到哪个段里,例如代码段,数据段等
  • 每一个段以段名为开始, 以下一个段名或者文件结尾为结束
  • .section name, “flags” 后面可以添加flags,表示段的属性。属性如下 image
  • .pushsection: 把下面的代码push到指定的section中
  • .popsection: 结束push 成对使用,仅仅是把 pushsection和popsection的圈出来的代码 加入到指定的section中,其他代码还是在原来的section

  • .macro和.endm组成一个 宏
  • .macro后面跟着的是宏的名称,在后面是宏的参数
  • 在宏里使用参数,需要添加前缀”\”
.macro plus1 p, p1
// 定义了一个名为plus1的宏,有两个参数p,和p1。
// 在宏里使用参数需要前缀,“\p” 表示第一个参数, “\p1”表示第二个参数
  • 宏参数定义的时候可以 设置一个初始化值
.macro reserve_str p1=0 p2
// 第一个参数p1有一个初始化的值,0。这时候你可以使用reserve_str a,b或者reserve_str ,b来调用这个宏

image 解决办法:

  • 使用空格 或者使用 altmacro+& image
  • 使用 “()” 表示 用来指示 字符串什么时候结束 image

Arm64编译选项

  • EB: 用于大端模式的CPU, -EL:用于小端模式的CPU
  • mabi:指定ABI模式,ilp32用于ELF32,lp64用于ELF64,默认值为lp64
  • mcpu=processor+extension:指定CPU型号,例如cortex-a72
  • march=,用于指定支持的架构,例如armv8.2-a
  • ARM64支持的extension,见第9.1.2章

特殊字符

  • “//” 注释
  • “#”:若在一行开始,表示注释。另外还可以表示立即数
  • “#:lo12”:表示低12位 adrp x0, foo ldr x0, [x0, #:lo12:foo ]

Arm64特有的伪操作

  • .bss: 切换到bss段
  • .dword/.xword: 64位数据
  • name .reg register_name: 为寄存器创建别名 foo .reg w0

jason--liu avatar Nov 27 '20 03:11 jason--liu