X86中mov和movl指令的区别?我在阅读汇编时遇到了一些麻烦[重复]

Posted

技术标签:

【中文标题】X86中mov和movl指令的区别?我在阅读汇编时遇到了一些麻烦[重复]【英文标题】:The difference between mov and movl instruction in X86? and I meet some trouble when reading assembly [duplicate] 【发布时间】:2018-06-05 07:41:39 【问题描述】:

最近,我读了一些关于计算机科学的书籍。我编写了一些 C 代码,并使用 gccobjdump 将它们反汇编。

以下C代码:

#include <stdio.h>
#include <stdbool.h>

int dojob()

    static short num[ ][4] =  2, 9, -1, 5,   3, 8, 2, -6;
    static short *pn[ ] = num[0], num[1];
    static short s[2] = 0, 0;
    int i, j;

    for (i=0; i<2; i++) 
        for (j=0; j<4; j++)
            s[i] += *pn[i]++;
        
        printf ("sum of line %d: %d\n", i+1, s[i]);
    

    return 0;


int main ( )

    dojob();

得到以下汇编代码(AT&T 语法;只有函数 dojob 的汇编和一些数据是列表):

00401350 <_dojob>:
  401350:   55                      push   %ebp
  401351:   89 e5                   mov    %esp,%ebp
  401353:   83 ec 28                sub    $0x28,%esp
  401356:   c7 45 f4 00 00 00 00    movl   $0x0,-0xc(%ebp)
  40135d:   eb 75                   jmp    4013d4 <_dojob+0x84>
  40135f:   c7 45 f0 00 00 00 00    movl   $0x0,-0x10(%ebp)
  401366:   eb 3c                   jmp    4013a4 <_dojob+0x54>
  401368:   8b 45 f4                mov    -0xc(%ebp),%eax
  40136b:   8b 04 85 00 20 40 00    mov    0x402000(,%eax,4),%eax
  401372:   8d 48 02                lea    0x2(%eax),%ecx
  401375:   8b 55 f4                mov    -0xc(%ebp),%edx
  401378:   89 0c 95 00 20 40 00    mov    %ecx,0x402000(,%edx,4)
  40137f:   0f b7 10                movzwl (%eax),%edx
  401382:   8b 45 f4                mov    -0xc(%ebp),%eax
  401385:   0f b7 84 00 08 50 40    movzwl 0x405008(%eax,%eax,1),%eax
  40138c:   00 
  40138d:   89 c1                   mov    %eax,%ecx
  40138f:   89 d0                   mov    %edx,%eax
  401391:   01 c8                   add    %ecx,%eax
  401393:   89 c2                   mov    %eax,%edx
  401395:   8b 45 f4                mov    -0xc(%ebp),%eax
  401398:   66 89 94 00 08 50 40    mov    %dx,0x405008(%eax,%eax,1)
  40139f:   00 
  4013a0:   83 45 f0 01             addl   $0x1,-0x10(%ebp)
  4013a4:   83 7d f0 03             cmpl   $0x3,-0x10(%ebp)
  4013a8:   7e be                   jle    401368 <_dojob+0x18>
  4013aa:   8b 45 f4                mov    -0xc(%ebp),%eax
  4013ad:   0f b7 84 00 08 50 40    movzwl 0x405008(%eax,%eax,1),%eax
  4013b4:   00 
  4013b5:   98                      cwtl   
  4013b6:   8b 55 f4                mov    -0xc(%ebp),%edx
  4013b9:   83 c2 01                add    $0x1,%edx
  4013bc:   89 44 24 08             mov    %eax,0x8(%esp)
  4013c0:   89 54 24 04             mov    %edx,0x4(%esp)
  4013c4:   c7 04 24 24 30 40 00    movl   $0x403024,(%esp)
  4013cb:   e8 50 08 00 00          call   401c20 <_printf>
  4013d0:   83 45 f4 01             addl   $0x1,-0xc(%ebp)
  4013d4:   83 7d f4 01             cmpl   $0x1,-0xc(%ebp)
  4013d8:   7e 85                   jle    40135f <_dojob+0xf>
  4013da:   b8 00 00 00 00          mov    $0x0,%eax
  4013df:   c9                      leave  
  4013e0:   c3                      ret    


Disassembly of section .data:

00402000 <__data_start__>:
  402000:   08 20                   or     %ah,(%eax)
  402002:   40                      inc    %eax
  402003:   00 10                   add    %dl,(%eax)
  402005:   20 40 00                and    %al,0x0(%eax)


Disassembly of section .bss:

...

00405008 <_s.1927>:
  405008:   00 00                   add    %al,(%eax)
    ...

我有两个问题:

    我不明白 movmovl 指令之间的区别?为什么编译器会为某些代码生成 mov,而为其他代码生成 movl

    我完全理解 C 代码的含义,但不理解编译器生成的程序集。谁能为它制作一些cmets让我理解?我会非常感谢。

【问题讨论】:

汇编代码很复杂,因为你编译时没有进行优化,导致编译器生成许多它可以不用的额外指令。 movl 是一个 mov,操作数大小为 32,如果从操作数中明确操作数大小,objdump 会省略 l 后缀。 您的反汇编程序仅在寄存器操作数未暗示大小的情况下使用l 操作数大小后缀。 (即立即存储到内存) Re:第 2 部分:请参阅 How to remove "noise" from GCC/clang assembly output?,了解如何从编译器中获得干净且更易于理解的 asm。 (包括使用 gcc -S 来获取符号名称而不是绝对地址。objdump -drwC 也会给你。) movl 中的 l 代表“long”,大小为 32 位 【参考方案1】:

MOVL 指令的生成是因为你放了两个int(i 和 j 变量),MOVL 将执行 32 位的 MOV,并且整数的大小为 32 位。

存在所有 MOV* 的非详尽列表(例如 MOVD 用于双字或 MOVQ 用于四字)以允许优化您的代码并使用更好的表达式来获得尽可能多的时间。

PS:可能是-M intel objdump 的说法可以帮助你更好地理解反汇编,很多人对Intel 语法可能很容易找到。

【讨论】:

movd 是不同的指令,而不是mov 的 AT&T 大小后缀。 felixcloutier.com/x86/MOVD:MOVQ.html。根据操作数,movq 是 64 位整数 mov,或者是 SSE2 整数向量指令

以上是关于X86中mov和movl指令的区别?我在阅读汇编时遇到了一些麻烦[重复]的主要内容,如果未能解决你的问题,请参考以下文章

什么时候应该在 x86 汇编中使用 MOVS 而不是 MOV?

x86 简单 mov 指令

x86汇编语言的MOV指令

arm指令中mov和ldr有啥区别?

arm汇编 ldr r0 =0x00000000 这个=号代表啥啊

GNU 汇编器 x86 指令后缀(如“mov.s”中的“.s”)如何工作?