【问题标题】:Best way to convert a Little Endian four byte long integer to Big Endian, or vice versa in x86 Assembly在 x86 汇编中将 Little Endian 四字节长整数转换为 Big Endian 的最佳方法,反之亦然
【发布时间】:2014-03-05 17:39:43
【问题描述】:

所以我想出了如何在 C 中反转四字节长 int 的字节序:

unsigned int swapWord (unsigned int n){
   return (n>>24) | ((n<<8) & 0x00FF0000) |((n>>8) & 0x0000FF00) | (n<<24);
}

现在我知道我可以反汇编它,而且我做到了,而且它是不错的代码,但我确信有一种更有效的方法来反转字节序。有什么想法吗?

编辑:这是反汇编代码:

00000000004005a3 <swapWord>:
      4005a3:   55                      push   %rbp
      4005a4:   48 89 e5                mov    %rsp,%rbp
      4005a7:   89 7d fc                mov    %edi,-0x4(%rbp)
      4005aa:   8b 45 fc                mov    -0x4(%rbp),%eax
      4005ad:   c1 e8 18                shr    $0x18,%eax
      4005b0:   89 c2                   mov    %eax,%edx
      4005b2:   8b 45 fc                mov    -0x4(%rbp),%eax
      4005b5:   c1 e0 08                shl    $0x8,%eax
      4005b8:   25 00 00 ff 00          and    $0xff0000,%eax
      4005bd:   09 c2                   or     %eax,%edx
      4005bf:   8b 45 fc                mov    -0x4(%rbp),%eax
      4005c2:   c1 e8 08                shr    $0x8,%eax
      4005c5:   25 00 ff 00 00          and    $0xff00,%eax
      4005ca:   09 c2                   or     %eax,%edx
      4005cc:   8b 45 fc                mov    -0x4(%rbp),%eax
      4005cf:   c1 e0 18                shl    $0x18,%eax
      4005d2:   09 d0                   or     %edx,%eax
      4005d4:   5d                      pop    %rbp
      4005d5:   c3                      retq   
      4005d6:   66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
      4005dd:   00 00 00 

【问题讨论】:

  • 反汇编代码是什么;它是一条bswap 指令吗?
  • 有反汇编代码。不,它比 bswap 指令更激烈一些。我用 bswap 搞砸了一点,但我猜不太明白。
  • 您在编译时是否指定了任何优化?这是相当微不足道的优化,gcc 在 O2 或以上发出 bswap
  • 对我来说,反汇编看起来像是 C 代码的字面翻译(根本没有启用优化)
  • @tannerwj C 代码的直译在这种情况下无济于事。在这种情况下,您实际上需要 O2。 O2 产生bswap eax

标签: assembly x86


【解决方案1】:

对于 80486 及更高版本,有一条名为 bswap 的指令用于交换双字中的字节。

对于较旧的 80386 CPU,我很想使用这样的东西:

                     ;eax = 0xAABBCCDD
    xchg ah,al       ;eax = 0xAABBDDCC
    rol eax,16       ;eax = 0xDDCCAABB
    xchg ah,al       ;eax = 0xDDCCBBAA

对于更旧的 CPU(8086 到 80286),您必须使用一对 16 位寄存器(因为没有 32 位寄存器),结果如下:

                     ;dx:ax = 0xAABBCCDD
                     ;ax:dx = 0xCCDDAABB
    xchg ah,al       ;ax:dx = 0xDDCCAABB
    xchg dh,dl       ;ax:dx = 0xDDCCBBAA

注意:您可以使用ror ax,8rol ax,8,而不是使用xchg ah,al。我怀疑你使用这 3 条指令中的哪一条会有很大的不同。

【讨论】:

  • 这看起来很有效。但是我是组装新手,你的组装类型和我的有什么区别?
  • 不同的是,这个是 Intel 语法,而你的反汇编是 AT&T 语法。代码是一样的。
猜你喜欢
  • 2011-02-09
  • 1970-01-01
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-12
  • 2012-10-09
相关资源
最近更新 更多