为什么组装需要在eax上重复操作movzx?

Why do assembly need repeated operation of movzx on eax?

提问人:Sreeraj Chundayil 提问时间:4/26/2020 最后编辑:Peter CordesSreeraj Chundayil 更新时间:4/26/2020 访问量:278

问:

代码 - 区别在于一种方法用于有符号的短 int-s,另一种方法用于无符号的短 int。

short signedShortIntSwap(short int* a , short int* b)
{
    short tmp = *a;
    *a = *b;
    *b = tmp;
    return *a;
}

unsigned short unsignedShortIntSwap(unsigned short int* a ,unsigned short int* b)
{
    unsigned short tmp = *a;
    *a = *b;
    *b = tmp;
    return *a;
}

集会:-gcc -c -m64 -o func1 func1.c -O2 -fno-tree-vectorize

0000000000000000 <signedShortIntSwap>:
   0:   f3 0f 1e fa             endbr64 
   4:   0f b7 07                movzx  eax,WORD PTR [rdi]
   7:   0f b7 16                movzx  edx,WORD PTR [rsi]
   a:   66 89 17                mov    WORD PTR [rdi],dx
   d:   66 89 06                mov    WORD PTR [rsi],ax
  10:   0f b7 07                movzx  eax,WORD PTR [rdi]
  13:   c3                      ret    
  14:   66 66 2e 0f 1f 84 00    data16 nop WORD PTR cs:[rax+rax*1+0x0]
  1b:   00 00 00 00 
  1f:   90                      nop

0000000000000020 <unsignedShortIntSwap>:
  20:   f3 0f 1e fa             endbr64 
  24:   0f b7 07                movzx  eax,WORD PTR [rdi]
  27:   0f b7 16                movzx  edx,WORD PTR [rsi]
  2a:   66 89 17                mov    WORD PTR [rdi],dx
  2d:   66 89 06                mov    WORD PTR [rsi],ax
  30:   0f b7 07                movzx  eax,WORD PTR [rdi]
  33:   c3                      ret    
  34:   66 66 2e 0f 1f 84 00    data16 nop WORD PTR cs:[rax+rax*1+0x0]
  3b:   00 00 00 00 
  3f:   90                      nop
  1. 为什么我们在地址 && 和 && 处对每个函数重复了 .movzx eax,WORD PTR [rdi]4102430
  2. 为什么有符号和无符号函数具有相同的指令集。在哪种情况下会有所不同?
C GCC x86-64 反汇编 内存锯齿

评论

1赞 Peter Cordes 4/26/2020
之所以使用 movzx,是因为它避免了您从 .与写入 32 位寄存器(隐式零扩展为 64 位)不同,写入 8 位或 16 位部分寄存器在逻辑上合并。(某些 CPU 会进行部分寄存器重命名以避免这种情况)。为什么 GCC 不使用部分寄存器?mov ax, [rdi]
1赞 Peter Cordes 4/26/2020
哦,你不是在问为什么是movzx,你是在问商店后重新加载EAX。那是因为 和 可能指向相同的 ,所以可能已经修改了。(更聪明的编译器会意识到,如果是这样的话,加载的两个值必须相同,因为它可以假设没有数据竞争 UB)。我会寻找另一个副本,如果我没有找到,我会重新打开。abshort*b = tmp*a
0赞 Peter Cordes 4/26/2020
相关:为什么编译器不再使用严格的别名来优化此 UB。回复:2.返回值的上位无关紧要,调用者需要忽略它们,因此 GCC 始终使用它来避免错误的依赖关系是件好事,因为它比某些 CPU 更快。movzxmovsx
0赞 Joseph Sible-Reinstate Monica 4/27/2020
看看如果将关键字添加到参数中,输出程序集将如何变化。restrict
0赞 Sreeraj Chundayil 4/27/2020
@JosephSible-ReinstateMonica:是的,它删除了额外的 movzx 语句。

答: 暂无答案