AT&T汇编基础知识
基本语法
AT&T与Inter汇编主要有以下几个不同:
- 寄存器的命名;
1
AT&T:%eax Intel:eax
- 源操作数与目的操作数的顺序;AT&T赋值方向为从左向右。
1
AT&T:movl %eax, %ebx Intel:mov ebx, eax
- 常数与立即数的格式;
1
AT&T:movl $12, %ebx Intel:mov eax, 12
- 地址;
1
AT&T:movl $0xd00d, %ebx Intel:mov eax, 0xd00d
- 操作数长度标识;
1
AT&T:movw %ax, %bx Intel:mov bx, ax
- 寻址方式;
1
2
3
4
5
6#通用寻址
AT&T:imm32(base, ip, scale) Intel:[base+ip×scale+imm32]
#直接寻址
AT&T:foo Intel:[foo]
#寄存器间接寻址
AT&T:(%eax) Intel:[eax]
GCC基本内联汇编
基本内联汇编的格式为:asm("statements");
GCC扩展内联汇编
GCC扩展内联汇编的格式为:
1 | asm [volatile]( Assembler Template |
注:如果不希望汇编语句被gcc优化而改变位置,就需要在asm符号后添加volatile关键词;
样例
1 | #define read_cr0() ({ \ |
说明
- 在
__asm__
的括号内,第一行为汇编程序模板;其中%0
以占位符作为汇编指令的操作数,GCC将这些占位符与C语言表达式按照出现的顺序相对应。即%0
对应C语言表达式__dummy
; - 第二行为输出部分;输出部分用来规定输出变量如何与寄存器结合的约束,输出部分可以有多个约束,互相以逗号分开,每个约束以”=”开头,接着用一个字母来表示操作数的类型,接着是关于变量结合的约束。在上例中,”r”代表任一通用寄存器,其他常用约束字母与含义见下表:
- 如果有输入部分;输入部分与输出部分相似,但是没有”=”;
- 汇编程序模板为必选项,输入部分与输出部分为可选项;当存在输入部分而不存在输出部分时,需要保留”:”(代表输出部分,即使输出部分不存在),而当只存在修改部分时,需要保留”:::”(代表输出部分、输入部分与修改部分);
练习
扩展内联汇编代码:
1 | int count=1; |
经过GCC编译之后得到的汇编代码为:
1 | movl count,%ecx |