我为 amd64 编写了这个小汇编文件。代码的作用对于这个问题并不重要。
.globl fib
fib: mov %edi,%ecx
xor %eax,%eax
jrcxz 1f
lea 1(%rax),%ebx
0: add %rbx,%rax
xchg %rax,%rbx
loop 0b
1: ret
然后我开始在 Solaris 和 Linux 上组装然后反汇编它。
太阳系
$ as -o y.o -xarch=amd64 -V y.s
as: Sun Compiler Common 12.1 SunOS_i386 Patch 141858-04 2009/12/08
$ dis y.o
disassembly for y.o
section .text
0x0: 8b cf movl %edi,%ecx
0x2: 33 c0 xorl %eax,%eax
0x4: e3 0a jcxz +0xa <0x10>
0x6: 8d 58 01 leal 0x1(%rax),%ebx
0x9: 48 03 c3 addq %rbx,%rax
0xc: 48 93 xchgq %rbx,%rax
0xe: e2 f9 loop -0x7 <0x9>
0x10: c3 ret
Linux
$ as --64 -o y.o -V y.s
GNU assembler version 2.22.90 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.22.90.20120924
$ objdump -d y.o
y.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <fib>:
0: 89 f9 mov %edi,%ecx
2: 31 c0 xor %eax,%eax
4: e3 0a jrcxz 10 <fib+0x10>
6: 8d 58 01 lea 0x1(%rax),%ebx
9: 48 01 d8 add %rbx,%rax
c: 48 93 xchg %rax,%rbx
e: e2 f9 loop 9 <fib+0x9>
10: c3 retq
生成的机器码怎么不一样? Sun 为 mov %edi,%ecx
生成 8b cf
,而 gas 为完全相同的指令生成 89 f9
。这是因为在 x86 下对同一指令进行编码的方式多种多样,还是这两种编码真的有特别的区别?
最佳答案
一些 x86 指令有多种编码来做同样的事情。特别是,任何作用于两个寄存器的指令都可以交换寄存器并反转指令中的方向位。
给定的汇编器/编译器选择哪一个完全取决于工具作者选择的工具。
关于linux - 为什么这里的 Solaris 汇编器生成的机器码与 GNU 汇编器不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17973103/