Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
jason--liu opened this issue Nov 27, 2020 · 0 comments
Open

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

jason--liu opened this issue Nov 27, 2020 · 0 comments
Labels

Comments

@jason--liu
Copy link
Owner

jason--liu commented Nov 27, 2020

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant