Intel和ATT汇编代码差异
下面是 CSAPP 原文
我们的表述是 ATT 可以产生 multstore 函数的 Intel 格式的代码:
linux> gcc -0g -s -masm=intel mstore. c
这个命令得到下列汇编代码:
multstore:
push rbx
mov rbx, rdx
call mult2
mov QWORD PTR [rbx], rax
pop rbx
ret我们看到 Intel 和 ATT 格式在如下方面有所不同:
- Intel 代码省略了指示大小的后缀。我们看到指令
push和mov,而不是pushq和movq. - Intel 代码省略了寄存器名字前面的
%符号,用的是rbx,而不是%rbx。 - Intel 代码用不同的方式来描述内存中的位置,例如是
QWORD PTR[rbx]而不是(%rbx)。 - Intel 立即数 (immediate), 也就是常数值,不使用前缀
$,如,十进制数123,不是$123;十六进制数123h,不是$0x123 - Intel 指令一般使用从右到左的顺序,而 ATT 使用从左到右,如 Intel 是
mov dst, src,而 ATT 是mov src, dst - AT&T 语法中立即数前面加一个字符
$;寄存器操作数名前要加字符百分号%;绝对跳转/调用(相对于与程序计数器有关的跳转/调用)操作数前面要加星号*。而 Intel 汇编语法均没有这些限制。 - AT&T 语法中内存操作数的长度(宽度)由操作码最后一个字符来确定。操作码后缀‘b’、‘w’和‘l’分别指示内存引用宽度为 8 位字节(byte)、16 位字(word)和 32 位长字(long)。Intel 语法则通过在内存操作数前使用前缀
byte prt、word ptr和dword ptr来达到同样的目的。因此,Intel 的语句mov al, byte ptr foo对应于 AT&T 的语句movb $foo, %al。
代码示例
int main(){
int a = 1;
int b = 2;
int c = a + b;
return 0;
}0000000000001129 <main>:
...
1131: c7 45 f4 01 00 00 00 movl $0x1,-0xc(%rbp)
1138: c7 45 f8 02 00 00 00 movl $0x2,-0x8(%rbp)
113f: 8b 55 f4 mov -0xc(%rbp),%edx
1142: 8b 45 f8 mov -0x8(%rbp),%eax
1145: 01 d0 add %edx,%eax
1147: 89 45 fc mov %eax,-0x4(%rbp)
114a: b8 00 00 00 00 mov $0x0,%eax
114f: 5d pop %rbp
1150: c3 retq
...通过 1145 和 1147 ,可以发现 %eax 是 dst, 代码格式为 ATT。