简介
AT&T 汇编语法,通常称为 GAS 语法(GNU as汇编器的语法, GAS=GNU Assembler)。
相对 ARM汇编指令, AT&T 汇编语法的不同处
1. 指令的长度后缀
AT&T语法要求在指令后面加上后缀表示长度,根据操作的是1字节、2字节、4字节、8字节,分别对应后缀b, w, l, q。
注:
如果不加后缀,默认是 w 。
字节(B) | 后缀字母 | 注释 |
---|---|---|
1 | b | BYTE |
2 | w | WORD |
4 | l | LONG |
8 | q | QUADWORD |
例如:
movq $1, %rax。
2. 跳转 和 函数调用 指令的语法
在 AT&T 汇编语法中,跳转、函数调用指令(jmp, jcc, call等)会涉及一些关于 寄存器Register、立即数Immediate、内存Memory的特殊使用方法,如下表所示:
上表给出了,如下所示:
- 寄存器 Register
寄存器语法:
例如:如果想要跳到寄存器*%寄存器
%rax
内容对应的地址,不是写成jmpq %rax,而是写成jmpq *%rax
- 立即数 Immediate
立即数语法:
如上表所示,不用加*号%立即数
- 内存 Memory
内存语法:
如果想要跳转到 %rip + 0x10 对应的地址,不是写成 jmpq 0x10(%rip) ,而是写成:*偏移量(%内存地址)
jmpq *0x10(%rip)
3. 指令寄存器相对寻址 (%rip-relative)
在x86_64汇编中,我们可以使用 指令寄存器 相对寻址 这种寻址方式来定位全局变量和函数。
例如:C代码中有一个全局变量a,我们可以使用a(%rip)来定位到该变量,而不是使用a来定位。
使用这种寻址方式能帮助我们编写出 position-independent code (PIC) 的代码,进而获取 position-independent executables (PIEs) 的执行文件。
关于PIC和PIE的概念,涉及程序链接的细节,这里暂时不讲。
注意:汇编器在解析汇编代码时,不是将a(%rip)中的a解析成a的地址,而是会将a解析成变量a的地址和当前%rip的偏移,这也是为什么这种语法寻址a可行的原因。
4. 一个AT&T汇编文件代码分为哪些部分
一个按AT&T语法写的汇编文件分为多个section,在 文档 中有说明,这些section包括:
- .text
代码段,该段包含可执行指令; - .rodata
只读数据段,用来存放只读数据。
例如:字符串字面量(String Literal)。 - .data
存放已初始化的全局变量和静态变量;
存放可读写的数据; - .bss
未初始化的全局变量和静态变量,在运行时该区域初始是全0。
.bss区域也可以用.comm/.lcomm和声明(https://sourceware.org/binutils/docs/as/bss.html#bss)
下面是一个C语言程序的内存布局,和汇编代码有一定的对应关系。
5. 如何编译和运行AT&T汇编代码
使用as命令对汇编文件进行汇编生成目标文件:
as xxx.s -o xxx.o
然后使用ld命令对目标文件进行链接生成可执行文件:
ld xxx.o -o xxx
注意:
ld命令进行链接要求目标文件的.text段必须有一个入口点,ld默认认为_start标签对应的代码是入口点。
例如下面的汇编代码:
.section .data
output:
.string "Hello\n"
.text
.globl _start
_start:
movq $1, %rax
movq %rax, %rsp # stack alignment
movq $1, %rdi
movq $output, %rsi
movq $6, %rdx
syscall
movq $60, %rax
xor %rdi, %rdi
syscall
上面的汇编代码可以正常汇编和链接,但是,如果将代码中的_start标签去掉,或者改成其他名称,在执行ld命令之后就会报告一个警告信息:
ld: warning: cannot find entry symbol _start; defaulting to 00000000004000b0
ld会默认给我们找一个入口点,有可能这个默认入口点是错误的,这样就会导致运行可执行文件出现错误。
原文链接:
https://blog.csdn.net/qq_29328443/article/details/107242121
状态:已核对