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 代码,并使用 gcc 和 objdump 将它们反汇编。
以下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)
...
我有两个问题:
我不明白 mov 和 movl 指令之间的区别?为什么编译器会为某些代码生成 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?