首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么Solaris汇编程序在这里生成与GNU汇编程序不同的机器代码?

为什么Solaris汇编程序在这里生成与GNU汇编程序不同的机器代码?
EN

Stack Overflow用户
提问于 2013-07-31 14:25:42
回答 2查看 421关注 0票数 5

我为amd64编写了这个小程序集文件。对于这个问题,代码所做的并不重要。

代码语言:javascript
运行
复制
        .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上拆卸它。

索拉里斯

代码语言:javascript
运行
复制
$ 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

代码语言:javascript
运行
复制
$ 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生成mov %edi,%ecx,而gas为同一指令生成89 f9。这是因为在x86下编码同一条指令的各种方式,还是这两种编码确实有特殊的区别?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-07-31 14:29:53

一些x86指令具有多个编码,这些编码可以完成相同的任务。特别是,在两个寄存器上工作的任何指令都可以交换寄存器,并反转指令中的方向位。

给定的汇编程序/编译器选择哪一个只取决于作者所选择的工具。

票数 6
EN

Stack Overflow用户

发布于 2013-08-05 20:42:14

您没有为movxoradd操作指定操作数大小。这就造成了一些模糊。GNU汇编程序手册i386记忆学提到了以下内容:

如果指令没有指定后缀,则尝试根据目标寄存器操作数(最后一个按惯例)填充缺失的后缀。...请注意,这与AT&T Unix汇编程序不兼容,后者假定缺少的助记符后缀意味着长操作数大小。

这意味着GNU汇编程序的选择不同--它将选择带有R/M字节指定目标操作数的操作码(因为目标大小为已知/隐含的),而AT&T则选择R/M字节指定源操作数的操作码(因为操作数大小是隐含的)。

不过,我已经做了这个实验,并在程序集源中给出了显式的操作数大小,并且它不改变GNU汇编程序输出。不过,上面还有文件的另一部分,

可以通过可选的助记符后缀指定不同的编码选项。当从一个寄存器移动到另一个寄存器时,“.s”后缀交换编码中的2寄存器操作数。

使用GNU as,下面的源代码创建了从Solaris as获得的操作码

代码语言:javascript
运行
复制
.globl fib

fib:    movl.s %edi,%ecx
        xorl.s %eax,%eax
        jrcxz 1f
        leal 1(%rax),%ebx

0:      addq.s %rbx,%rax
        xchgq %rax,%rbx
        loop 0b

1:      ret
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17973103

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档